A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© juanjuan 中级黑马   /  2016-10-9 23:37  /  2049 人查看  /  6 人回复  /   6 人收藏 转载请遵从CC协议 禁止商业使用本文

借用用sleep方法影响cpu的执行,详细分析死锁、wait、notify
一个模拟stack类,用两个线程分别调用get和push方法【代码自己加】,此时(1)和(2)代码不能同时存在,如果都存在就会互相等待,无论后面有没有notify,程序卡住不动。
1,如果打开(1)的注释,同上,一定保证cup先调用get线程,因为有o1.wait(),程序会先执行push,再执行get,并且在push后要o1.notify();【即(4)代码不能注释】否则程序卡住。可以试试把(4)注释起来
2,如果没有保证cup先调用get线程,可以试着打开(7)的注释,此时尽管get线程先start,但实际上cpu并没有进入get代码块,是push线程先执行,也就是说此时o1.notify先于o1.wait执行,程序就只执行push,然后卡死,如果此时再打开(6),就又会执行push再执行get正常结束。
3,如果打开(5),程序会抛出java.lang.IllegalMonitorStateException异常,此时get线程的o1锁虽然已经wait,但push线程并没有持有o1锁,所以抛出异常,必须让代码执行到内层同步块,才能调用o1.notify,正常唤醒o1锁。
4,如果是push线程先start,就正好反过来,要注释掉(1)和(4),打开(2)和(3),此时程序因为在push代码块的第一层让o2.wait,所以程序会先执行get,哪怕在get中sleep,因为是在同步块中,cpu是不会跳出的,执行完之后再o2.notify,唤醒o2执行完push中剩下的内层代码块。
总之,多线程时程序一定是多个流程同时执行,当进入同步代码块的时候,就不会再跳出了,为了有可能出现的死锁(可能是W分之一),就要搞的这么复杂,实在是太不值了,还是尽量避免这样嵌套的情况发生吧
public class MyStack {
Object o1 = new Object();
Object o2 = new Object();
public void get() throws Exception {
//Thread.sleep(100);//(7)
synchronized (o1) {
o1.wait();//(1)
synchronized (o2) {
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
System.out.println("这是get--" + i);
}
//o2.notify();//(3)
} } }

public void push() throws Exception {
synchronized (o2) {
//o1.notify();//(5)
//Thread.sleep(100);//(6)
//o2.wait();//(2)
synchronized (o1) {
for (int i = 0; i < 10; i++) {

System.out.println("这是push--" + i);
}
o1.notify();//(4)
} }
}
}

6 个回复

倒序浏览
回复 使用道具 举报
up!谢楼主啦~~~~
来自宇宙超级黑马专属苹果客户端来自宇宙超级黑马专属苹果客户端
回复 使用道具 举报
谢谢楼主了
回复 使用道具 举报
感谢分享。。赞一个。。
回复 使用道具 举报
谢谢楼主分享
回复 使用道具 举报
感谢分享
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马