利用Java多线程实现死锁现象之详细解读

这个例子个人觉得非常经典,先看完,讲解在下面啦,(^__^) 嘻嘻!

/*
 * 死锁:
 * 同步中嵌套同步,而锁不同。
 * 都在等待对方线程中的锁释放。
 * */
public class Demo8 {
    public static void main(String[] args) {
        // 创建了一个ticket对象
        Ticket2 t = new Ticket2();
        // 创建了2个线程
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        // 启动线程t1
        t1.start();
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t.flag = false;
        // 启动线程t2
        t2.start();
    }
}

class Ticket2 implements Runnable {
    private int tick = 100;
    Object obj = new Object();
    boolean flag = true;

    public void run() {
        if (flag) {
            while (true) {
                synchronized (obj) {
                    System.out.println("cccc");
                    // 调用show
                    show();
                }
            }
        } else {
            while (true) {
                System.out.println("ddddd");
                show();
            }
        }
    }

    public synchronized void show() {// 这里有两把锁 函数(this) obj
        System.out.println("aaaa");
        synchronized (obj) {
            System.out.println("bbbb");
            if (tick > 0) {
                try {
                    Thread.sleep(10);
                    System.out.println(Thread.currentThread().getName()
                            + "code...." + tick--);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    }
}

结果为(各种可能,这个可能是我特意多次运行等到的结果,因为这个结果讲起来才更具代表性):并手动对其进行了一个编号

cccc                     1
aaaa                     2
bbbb                     3
ddddd                     4
Thread-0code....100                     5
cccc                     7
aaaa                     8
bbbb                     9
Thread-0code....99                     10
cccc                     11
aaaa                     12

现在对其产生的原因进行详细讲解:
首先创建了两个线程(新生态),t1先启动,flag为true,那么obj先上锁,输出cccc,然后调用show()方法,这里上了第二道锁,输出了aaaa,因为有相同的obj的锁,所以可以进入输出bbbb,为何后面是ddddd呢,因为bbbb之后休眠了10毫秒此时flag改为了false后,t2启动执行else中的代码所以才有的ddddd,休眠结束后输出Thread-0code。。。。100。对于if中始终都持有obj这把锁(预测很容易发生死锁,马上就要了,(^__^) 嘻嘻,坚持看下去),接下来的cccc是因为被t1抢到了,然后是因为t1还猛些,抢到了第二把锁synchronized,同理输出aaaa、bbbb,然后输出“Thread-0code…..99”,(关键点马上就来了,马上死锁了,最后两行代码了还剩),此时t1还是有obj这把锁,t1继续执行while循环,先遇到synchronized(obj),可以进入,因为obj当前在t2手上,输出cccc后即可就要进入show()方法了。但是不幸的是,(show()方法有synchronized关键字修饰,表示该方法有锁)被t2抢到了show这把锁,进入show()后立刻上锁,输出aaaa,可是现在t2需要obj这把锁,可是这把锁t1拿着的,所以需要等待t1释放obj这把锁,然而t1等待着show的这把锁释放呢,所以两个就在相互的等待中了,从而进入了传说中的死锁状态。

可能各位看着上面的话语太多,并且前面的“结果中的行号”并没有什么乱用,因为实在不好描述(不能用画画的方式即时演示),可是若是一点一点的看的话,将会对死锁有非常透彻的理解,希望各位看到此段话的时候,能够抱着一定要理解“死锁”的心态去阅读。有何问题在评论中留言,我会在2个工作日内回复的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值