关于线程同步中的死锁问题

关于线程同步中的死锁问题

创建一个含有int属性的类Temp,创建一个实现Runnable接口的类Demo1,其中有boolean类属性flag和静态属性Temp类的o1和o2,写成静态属性是为了在实例不同Demo1对象的时候调用共同的o1和o2对象。Demo1中有run方法,run方法中根据flag值的不同执行不同的语句。在测试的时候,创建两个线程并对其flag赋不同的值。图一和图二的区别就是图一是在run方法中在synchronized一个对象之后synchronized另一个对象(图1),也就是必须满足同时synchronized两个对象才能结束线程。图2是在run方法中在synchronized一个对象之后访问另一个对象(图2),也就是synchronized一个对象并访问另一个对象就可以结束线程。具体代码如下:

死锁的图一:

http://img1.sycdn.imooc.com//climg/5a6540dd00019f4a04670799.jpg

没有死锁的图2:

http://img1.sycdn.imooc.com//climg/5a6540f2000114f504620802.jpg

不是很理解为什么只有图一死锁,图一中创建的两个线程flag值相反,t1先synchronized对象o1,之后sleep,这时候t2执行,synchronized对象o2,之后sleep,之后t1sleep结束,要求synchronized对象o2否则线程不会结束也就不会释放o1,但是此时o2被t2锁定,同时t2要求synchronized对象o1否则线程不会结束也就不会释放o2。这样两个线程互斥谁都不会结束造成死锁。

但是图二为什么不会死锁呢?图二中创建的两个线程flag值相反,t1先synchronized对象o1,之后sleep,这时候t2执行,synchronized对象o2,之后sleep,之后t1sleep结束,要求访问对象o2否则线程不会结束也就不会释放o1,但是此时o2被t2锁定,同时t2要求访问对象o1否则线程不会结束也就不会释放o2。与图一的不同仅仅是在synchronized一个对象之后要求访问另一个对象而不是synchronized另一个对象。但是当一个对象被一个线程synchronized的时候是不允许其他线程访问的啊!所以我认为图二也会死锁。但是为什么实际运行的时候图二并不会死锁呢?

正在回答

登陆购买课程后可参与讨论,去登陆

2回答

静态变量本身是多个对象间可以共享的,所以虚拟机是支持不同对象对静态变量的修改的。而在你的程序中,给静态变量加锁就会出现一些意料之外的情景。比如你所说的死锁问题,我试着在下面的代码中写了一条输出语句,发现这个同步代码块不是因为对象锁定不能修改变量,而是代码块根本就没有执行。所以,建议可以根据视频中提到的应用场景去解决类似的问题,而对于这些尝试的内容不要太过于纠结,因为有些情况是同步不适用的场景。不过有探索精神还是很好哒!祝学习愉快!

synchronized(o2){

System.out.println("ok1-middle1");

o2.i=5;

}


  • 大佬金 提问者 #1
    非常感谢!
    2018-01-23 14:08:55
一叶知秋519 2018-01-22 14:38:45

图2是分别锁了两个资源o1 和o2,当t1执行时,锁定的是o1,但是o2并没有锁定,假设o2锁定,可以等t2休眠结束程序运行结束后再执行,也就是等其中一个执行完之后再执行,这样可以没有死锁的;而你的图一是两个资源都进行锁定,都会竞争同一个资源所以会死锁。建议再看一下例题。祝学习愉快~

  • 提问者 大佬金 #1
    t1执行的时候的确锁定的是o1,但是当t1要访问o2的时候o2势必是被锁定的啊,因为t1经历了一段休眠,t2是会锁定o2的。至于“假设o2锁定,可以等t2休眠结束程序运行结束后再执行”,线程t2休眠结束后不会直接结束线程啊,t2要在访问o1之后才能结束,但是o1在最初就被t1锁定了。
    2018-01-22 21:58:30
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师