引言:
java开发中当某些逻辑设计得不合理时,将会出现“线程死锁”的问题。
线程死锁
- 不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁
- 出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续。当我们使用Java中的同步机制时要避免出现死锁。
线程死锁演示 1:
public class DeadLockTest {
    public static void main(String[] args) {
        StringBuffer s1 = new StringBuffer();
        StringBuffer s2 = new StringBuffer();
        new Thread() {
            @Override
            public void run() {
                synchronized (s1) {
                    s1.append("a");
                    s2.append("1");
                    try {
                        sleep(1000);//强行休眠,提高出现死锁的概率,达到演示效果
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (s2) {
                        s1.append("b");
                        s2.append("2");
                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }.start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (s2) {
                    s1.append("c");
                    s2.append("3");
                    try {
                        Thread.sleep(1000);//强行睡眠,提高出现死锁的概率,达到演示效果
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (s1) {
                        s1.append("d");
                        s2.append("4");
                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }).start();
    }
}第一个线程握住s1锁,等待其他线程释放s2锁;第二个线程握住s2锁,等待其他线程释放s1锁。两个线程都在等待对方放弃自己需要的同步资源,出现死锁。
线程死锁演示 2:
class A {
    public synchronized void foo(B b) {//非静态方法同步监视器为this:A类的对象a
        System.out.println("当前线程名:" + Thread.currentThread().getName() + " 进入了A实例的foo()方法");
        try {
            Thread.sleep(1000);//强行休眠,提高出现死锁的概率,达到演示效果
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("当前线程名:" + Thread.currentThread().getName() + " 企图调用B实例的last()方法");
        b.last();
    }
    public synchronized void last() {//非静态方法同步监视器为this:A类的对象a
        System.out.println("进入了A类的last()方法内部");
    }
}
class B {
    public synchronized void bar(A a) {//非静态方法同步监视器为this:B类的对象b
        System.out.println("当前线程名:" + Thread.currentThread().getName() + " 进入了B实例的bar()方法");
        try {
            Thread.sleep(1000);//强行休眠,提高出现死锁的概率,达到演示效果
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("当前线程名:" + Thread.currentThread().getName() + " 企图调用A实例的last()方法");
        a.last();
    }
    public synchronized void last() {//非静态方法同步监视器为this:B类的对象b
        System.out.println("进入了B类的last()方法内部");
    }
}
class DeadLock implements Runnable {
    A a = new A();
    B b = new B();
    public void init() {
        Thread.currentThread().setName("主线程");
        a.foo(b);//调用a对象的foo()方法
        System.out.println("主线程结束");
    }
    @Override
    public void run() {
        Thread.currentThread().setName("副线程");
        b.bar(a);//调用b对象的bar()方法
        System.out.println("副线程结束");
    }
}
public class DeadLockTest {
    public static void main(String[] args) {
        DeadLock dl = new DeadLock();
        new Thread(dl).start();
        dl.init();
    }
}减少死锁的出现,自己体会
class A {
    public synchronized void foo(B b) {//非静态方法同步监视器为this:A类的对象a
        System.out.println("当前线程名:" + Thread.currentThread().getName() + " 进入了A实例的foo()方法");
        System.out.println("当前线程名:" + Thread.currentThread().getName() + " 企图调用B实例的last()方法");
        b.last();
    }
    public synchronized void last() {//非静态方法同步监视器为this:A类的对象a
        System.out.println("进入了A类的last()方法内部");
    }
}
class B {
    public synchronized void bar(A a) {//非静态方法同步监视器为this:B类的对象b
        System.out.println("当前线程名:" + Thread.currentThread().getName() + " 进入了B实例的bar()方法");
        System.out.println("当前线程名:" + Thread.currentThread().getName() + " 企图调用A实例的last()方法");
        a.last();
    }
    public synchronized void last() {//非静态方法同步监视器为this:B类的对象b
        System.out.println("进入了B类的last()方法内部");
    }
}
class DeadLock implements Runnable {
    A a = new A();
    B b = new B();
    public void init() {
        Thread.currentThread().setName("主线程");
        //调用a对象的foo()方法
        a.foo(b);
        System.out.println("主线程结束");
    }
    @Override
    public void run() {
        Thread.currentThread().setName("副线程");
        //调用b对象的bar()方法
        b.bar(a);
        System.out.println("副线程结束");
    }
}
public class DeadLockTest {
    public static void main(String[] args) {
        DeadLock dl = new DeadLock();
        new Thread(dl).start();
        //增加"不出现死锁"的概率
        try {
            Thread.sleep(1000);//主线程休眠
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        dl.init();
    }
}
//可能的输出
/**
当前线程名:副线程 进入了B实例的bar()方法
当前线程名:副线程 企图调用A实例的last()方法
进入了A类的last()方法内部
副线程结束
当前线程名:主线程 进入了A实例的foo()方法
当前线程名:主线程 企图调用B实例的last()方法
进入了B类的last()方法内部
主线程结束
**/解决办法
- 专门的算法、原则
- 尽量减少同步资源的定义
- 尽量避免嵌套同步
 
                     
                     
                        
                        