java中死锁_关于java中死锁的总结
關(guān)于死鎖,估計很多程序員都碰到過,并且有時候這種情況出現(xiàn)之后的問題也不是非常好排查,下面整理的就是自己對死鎖的認(rèn)識,以及通過一個簡單的例子來來接死鎖的發(fā)生,自己是做python開發(fā)的,但是對于死鎖的理解一直是一種模糊的概念,也是想過這次的整理更加清晰的認(rèn)識這個概念。
用來理解的例子是一個簡單的生產(chǎn)者和消費者模型,這里是有一個生產(chǎn)者,有兩個消費者,并且注意代碼中使用notify方法的代碼行
packagestudy_java.ex11;importjava.util.LinkedList;importjava.util.List;public classPCDemo1 {public static voidmain(String[] args){
Pool pool= newPool();
Producter p1= newProducter(pool);
p1.setName("p1");
Consumer c1= newConsumer(pool);
Consumer c2= newConsumer(pool);
c1.setName("c1");
c2.setName("c2");
p1.start();
c1.start();
c2.start();
}
}classPool{private List list = new LinkedList();private int Max = 1;public void addLast(intn){
String name=Thread.currentThread().getName();synchronized (this){while (list.size() >=Max){try{
System.out.println(name+".wait()");this.wait();
}catch(Exception e){
e.printStackTrace();
}
}
System.out.println(name+ "+" +n);
list.add(newInteger(n));
System.out.println(name+ ".notify()");this.notify(); //注意這里是調(diào)用的是notify方法
}
}public intremove(){
String name=Thread.currentThread().getName();synchronized (this){while (list.size() == 0){try{
System.out.println(name+ ".wait()");this.wait();
}catch(Exception e){
e.printStackTrace();
}
}
System.out.println(name+ "-" + 0);int no = list.remove(0);
System.out.println(name+ ".notify()");this.notify(); //注意這里是調(diào)用的是notify方法
returnno;
}
}
}//生產(chǎn)者
class Producter extendsThread{privatePool pool;static int i = 1;publicProducter(Pool pool){this.pool =pool;
}public voidrun(){while (true){
pool.addLast(i++);
System.out.println("生產(chǎn)者生產(chǎn)了"+i+"號");
}
}
}//消費者
class Consumer extendsThread{privatePool pool;publicConsumer(Pool pool){this.pool =pool;
}public voidrun(){while (true){int no =pool.remove();
System.out.println("消費者消費了"+no+"號");
}
}
}
這段代碼的運行效果是日志,在最后程序卡主不動了:
c1.wait()
p1+1p1.notify()
c1-0c1.notify()
消費者消費了1號
c1.wait()
生產(chǎn)者生產(chǎn)了2號
p1+2p1.notify()
c1-0c1.notify()
消費者消費了2號
c1.wait()
生產(chǎn)者生產(chǎn)了3號
p1+3p1.notify()
c1-0c1.notify()
消費者消費了3號
c1.wait()
生產(chǎn)者生產(chǎn)了4號
p1+4p1.notify()
c1-0c1.notify()
消費者消費了4號
c1.wait()
生產(chǎn)者生產(chǎn)了5號
p1+5p1.notify()
c1-0c1.notify()
消費者消費了5號
c1.wait()
生產(chǎn)者生產(chǎn)了6號
p1+6p1.notify()
生產(chǎn)者生產(chǎn)了7號
c1-0c1.notify()
消費者消費了6號
c1.wait()
p1+7p1.notify()
生產(chǎn)者生產(chǎn)了8號
p1.wait()
c2-0c2.notify()
消費者消費了7號
c2.wait()
c1.wait()
p1+8p1.notify()
生產(chǎn)者生產(chǎn)了9號
p1.wait()
c2-0c2.notify()
消費者消費了8號
c2.wait()
c1.wait()
對上面的出現(xiàn)卡主的情況進(jìn)行分析,理解為啥會卡主:
從這次的執(zhí)行效果可以看出第一次是c1搶到了執(zhí)行權(quán),但是這個時候pool是空
所以c1沒有可以消費的對象,被放入到了等待隊列
接著p1搶到了執(zhí)行權(quán),生產(chǎn)了1個,然后p1.notify(),這個時候等待隊列里只有c1,所以c1被喚醒,c1消費了1個,然后c1.notify(), 這個時候等待隊列也沒有等待的,這個時候有被c1搶到了執(zhí)行權(quán),但是pool里沒有可以消費的內(nèi)容,所以c1.wait() 進(jìn)入到等待隊列
這個時候p1搶到執(zhí)行權(quán),生產(chǎn)了1個,然后p1.notify(),這個時候等待隊列里只有c1,所以c1被喚醒,c1也搶到了執(zhí)行權(quán),消費了1個,然后c1.notify()
同樣這個時候等待隊列里沒有等待的,c1這次又搶到了執(zhí)行權(quán),但pool里沒有可以消費的內(nèi)容,所以c1.wait(),進(jìn)入到等待隊列
p1 又搶到了執(zhí)行權(quán),生產(chǎn)1個,然后p1.notify(),這個時候等待隊列里只有c1,所以c1被喚醒,c1也搶到了執(zhí)行權(quán),消費了1個,然后c1.notify()
同樣這個時候等待隊列里沒有等待的,c1這次又搶到了執(zhí)行權(quán),但pool里沒有可以消費的內(nèi)容,所以c1.wait(),進(jìn)入到等待隊列
.......這種情況重復(fù)了幾次
但是運行到下面這段的時候問題出現(xiàn)了:
p1+7p1.notify()
生產(chǎn)者生產(chǎn)了8號
p1.wait()
c2-0c2.notify()
消費者消費了7號
c2.wait()
c1.wait()
p1+8p1.notify()
生產(chǎn)者生產(chǎn)了9號
p1.wait()
c2-0c2.notify()
消費者消費了8號
c2.wait()
c1.wait()
繼續(xù)進(jìn)行分析,中間重復(fù)的部分不做分析了,和前面的過程是一樣的
這個時候等待隊里里依然是c1 這個時候p1搶到了執(zhí)行權(quán),生產(chǎn)了1個,p1.notify() 這個時候等待隊列里只有c1,所以c1被喚醒,但是c1沒有搶過p1,p1自己又搶到了執(zhí)行權(quán),但是這個時候pool里面已經(jīng)有內(nèi)容,所以p1沒有生產(chǎn),p1.wait(),p1進(jìn)入等待隊列
這個時候c2搶到了執(zhí)行權(quán),c2消費1個,c2.notify() 這個時候等待隊里是p1,p1被喚醒,但是這個時候c2搶到了執(zhí)行權(quán),但是pool沒有內(nèi)容可以消費所以c2.wait() 進(jìn)入等待隊列
接著c1搶到了執(zhí)行權(quán),同樣pool沒有可以消費的內(nèi)容,c1.wait() 進(jìn)入到等待隊列
p1這個時候搶到了執(zhí)行權(quán),p1生產(chǎn)了1個,接著p1.notify() 這個時候等待隊列里有c1和c2,但是只有一個會被喚醒,不管是哪個,結(jié)果沒搶過p1,p1再次拿到執(zhí)行權(quán),但是這個時候pool已經(jīng)有內(nèi)容,所以p1.wait() p1進(jìn)入等待隊列
從下面是c2執(zhí)行,可以看出剛才是c2被喚醒了,這個時候c2也拿到了執(zhí)行權(quán)消費了1個。c2.notify() 等待隊列里這個時候有c1 和p1 但是這個時候c2 自己搶到了執(zhí)行權(quán),但是沒有可以消費的,c2.wait() c2 進(jìn)入等待隊列
不巧的是剛才搶到執(zhí)行權(quán)的正好是c1,所以c1繼續(xù)wait,再次進(jìn)入等待隊列
到這個時候p1 c1 c2 都進(jìn)入等待隊列里,都在等待喚醒,也就出現(xiàn)了程勛最后卡住不動的情況
解決的方法有兩種:
第一種:
其實解決上面的方法也比較簡單,就是把調(diào)用notify的地方全部換成notifyAll方法
notify和notifyAll的區(qū)別是,當(dāng)執(zhí)行notifyAll的時候會喚醒所有等待的線程,從而避免之前的都在等待隊列等待的問題
第二種:
就是wait()的時候加上超時參數(shù),不是像之前一直傻等,而是在超過既定的時間之后自己喚醒
總結(jié)
以上是生活随笔為你收集整理的java中死锁_关于java中死锁的总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何关闭借呗订阅开通通知_支付宝花呗借呗
- 下一篇: c语言编程算法精选,c语言经典程序算法【