利用Java多线程实现死锁现象之详细解读
2015-07-29 01:11
387 查看
这个例子个人觉得非常经典,先看完,讲解在下面啦,(^__^) 嘻嘻!
结果为(各种可能,这个可能是我特意多次运行等到的结果,因为这个结果讲起来才更具代表性):并手动对其进行了一个编号
现在对其产生的原因进行详细讲解:
首先创建了两个线程(新生态),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个工作日内回复的。
/* * 死锁: * 同步中嵌套同步,而锁不同。 * 都在等待对方线程中的锁释放。 * */ 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个工作日内回复的。
相关文章推荐
- Spring RMI
- Java设计模式之工厂模式
- 解决MyEclipse添加自定义库后,提示class not found
- Java多态学习总结
- 黑马程序员——Java基础---泛型、集合框架工具类:Collections和Arrays、JDK 1.5新特性
- 浅谈Java多线程中的Thread.sleep()和wait()方法的区别
- java实现上传和下载工具类
- Ubuntu12.04 install JDK 1.8.0_05
- Java远程调用邮件服务器,实现邮件发送
- C# MD5 与 java MD5 生成的字符串不一致问题
- 【SpringMVC架构】SpringMVC介绍(一)
- 【SpringMVC架构】SpringMVC介绍(一)
- java中的并发:进程和线程
- 项目实录之集成Mybatis
- 项目实录之Shiro的使用
- java日志组件介绍(common-logging,log4j,slf4j,logback )
- java中的并发:进程和线程
- java web 资源地址写法
- eclipse的使用-------Text File Encoding没有GBK选项的设置
- struts.xml的结构