多线程死锁:同步中嵌套同步,导致锁无法释放

死锁解决办法:不要在同步中嵌套同步

public class Demo06DeadLock {
    public static void main(String[] args) {
        //创建线程任务对象
        Ticket ticket = new Ticket();
        //创建三个窗口对象
        Thread t1 = new Thread(ticket, "窗口1");
        Thread t2 = new Thread(ticket, "窗口2");
        Thread t3 = new Thread(ticket, "窗口3");
        //卖票
        t1.start();
        t2.start();
        t3.start();
    }

    static class Ticket implements Runnable {
        Object obj = new Object();
        private int ticket = 100;

        public void run() {
            String name = Thread.currentThread().getName();
            while (true) {
                if ("窗口1".equals(name)) {
                    synchronized (obj) {
                        sell(name);
                    }
                } else {
                    sell(name);
                }
                if (ticket <= 0) {
                    break;
                }
            }
        }

        private synchronized void sell(String name) {
            synchronized (obj) {
                if (ticket > 0) {
                    System.out.println(name + "卖票:" + ticket);
                    ticket--;
                }
            }
        }
    }
}

同步方法的同步锁是谁:

1、对于非static方法,同步锁就是this。

2、对于static方法,我们使用当前方法所在类的字节码对象(类名.class)。

分析:

同步代码块的锁是obj,同步方法的锁是this,窗口1先获取obj,再获取this,再获取obj,即窗口1要三次获取锁。窗口2和窗口3先获取this,再获取obj,当窗口1获取了obj后等待this,而窗口2获取了this而等待obj,此时出现了死锁。

结果为:

 买到第14张票时,程序为继续卖票也未停止执行。

再次运行,会出现如下结果:只卖1张票,程序就不再继续卖票且未结束。

 网络上关于死锁的内容:

所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。

因此我们举个例子来描述,如果此时有一个线程A,按照先锁a再获得锁b的的顺序获得锁,而在此同时又有另外一个线程B,按照先锁b再锁a的顺序获得锁。如下图所示:

 

 

 

 

 

posted on 2021-02-25 09:56  周文豪  阅读(86)  评论(0编辑  收藏  举报