ACAC 死锁(synchronized嵌套)

package DeadLock;

public class Test01 {
    public static void main(String[] args) {

        Object o1 = new Object();
        Object o2 = new Object();

        //两个线程共享o1,o2
        MyThread a = new MyThread(o1,o2);
        MyThread02 b = new MyThread02(o1,o2);


        a.start();
        b.start();

        //问:为什么可以正常执行?a或者b可能先执行,将o1,o2锁住后,立马就释放了
        //然后另一个程序就开始锁o1,o2了,这样是可以正常执行

        /**
         * 问题1:为什么是o1,o2,o2,o1的上锁形式,不是o1,o2,o1,o2呢?
         *      如果是o1,o2,o1,o2的形式,即使是都睡了
         *        那也不影响,因为a中的o1,睡醒后,去锁o2,这个时候b要锁o1,o1已被a占了
         *        只能等到a中的o1,锁了o2后再将o2,o1释放,b就可以进行锁了(睡不睡无所谓)
         *      而如果是o1,o2,o2,o1的形式,如果两个都睡了
         *        好家伙,a先把o1给锁了,醒了要锁o2,但b已经把o2锁了,醒了要找o1,两把锁都找不到
         *        尴尬了,都停在锁池里面,找锁
         * 问题2:为什么o1,o2,o2,o1的形式,不睡的话可以正常执行呢?
         *      这其实是a.start()执行后,很快啊,就把o1,o2给锁了,然后又释放了
         *      等到b.start()执行后,run方法里,去找锁时,就能找到了
         *
         * 问题3:为什么这种死锁的形式,当只有一个线程睡眠的时候,有时会成死锁,有时不会呢?
         *      这和它的代码是有关系的:如 a.start();
         *                             b.start();
         *      这样的话,如果a的run方法中没有睡眠的话,b中有睡眠也可以的,不会造成死锁的
         *      但是如果将b.start()放在上面的话,就会造成死锁的,因为b虽然先执行run方法
         *      但是睡了1000毫秒,而a.start()在这1000毫秒内早执行了,b睡醒后,要锁o1
         *      但o1已经被a锁住了,而a想找o2,但b先执行的,没睡之前就给o2锁住了,所以成了死锁。
         *
         * 结论:synchronized最好不要在开发中嵌套使用,一不小心就会发生死锁,不好调试
         */
    }
}
class MyThread extends  Thread{
    Object o1;
    Object o2;
    public MyThread(Object o1,Object o2){
        this.o1 = o1;
        this.o2 = o2;
    }

    @Override
    public void run() {
        synchronized(o1){
           /* try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }*/
            synchronized (o2){

            }
        }
    }
}
class MyThread02 extends Thread{
    Object o1;
    Object o2;

    public MyThread02(Object o1, Object o2) {
        this.o1 = o1;
        this.o2 = o2;
    }

    @Override
    public void run() {
        synchronized (o2){
             try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (o1){

            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_44707513/article/details/110749400