关于线程同步中的死锁问题
创建一个含有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一个对象并访问另一个对象就可以结束线程。具体代码如下:
死锁的图一:
没有死锁的图2:
不是很理解为什么只有图一死锁,图一中创建的两个线程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的时候是不允许其他线程访问的啊!所以我认为图二也会死锁。但是为什么实际运行的时候图二并不会死锁呢?
正在回答
静态变量本身是多个对象间可以共享的,所以虚拟机是支持不同对象对静态变量的修改的。而在你的程序中,给静态变量加锁就会出现一些意料之外的情景。比如你所说的死锁问题,我试着在下面的代码中写了一条输出语句,发现这个同步代码块不是因为对象锁定不能修改变量,而是代码块根本就没有执行。所以,建议可以根据视频中提到的应用场景去解决类似的问题,而对于这些尝试的内容不要太过于纠结,因为有些情况是同步不适用的场景。不过有探索精神还是很好哒!祝学习愉快!
synchronized(o2){
System.out.println("ok1-middle1");
o2.i=5;
}
- 参与学习 人
- 提交作业 7317 份
- 解答问题 14452 个
想要入门学编程?多年一直活跃在编程语言排行版前列的Java是一个很好的选择。本路径将从Java基础语法、面向对象、常用工具类三部分,为你开启软件开发的大门!
了解课程
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星