Posted on 2012-06-16 22:22
steven.cui 閱讀(509)
評論(0) 編輯 收藏 所屬分類:
java
業(yè)務(wù)上線后,在有大量并發(fā)后,出現(xiàn)了一個線程完全被占用的問題,后來通過得到j(luò)vm堆棧信息(kill -3)看出來是死鎖問題。
由于業(yè)務(wù)邏輯代碼實(shí)在比較復(fù)雜,此處濾掉業(yè)務(wù)代碼把線程競爭關(guān)系展示出來:
1線程———>獲得A鎖———>獲得B鎖———>釋放B鎖————>釋放A鎖
2線程———>獲得A鎖———>釋放A鎖
3線程-——————>獲得B鎖———>獲得A鎖
問題就出在1和3線程之間的AB鎖嵌套導(dǎo)致死鎖問題,1線程在沒有獲得B鎖的時(shí)候,3線程開始獲得B鎖然后又得到了A鎖,這時(shí)候就完全釋放不了A鎖了,死鎖產(chǎn)生了。
由于時(shí)間關(guān)系,問題是理清楚了,只要刪掉1線程的A鎖就可以了,當(dāng)時(shí)還是仔細(xì)了解過是否刪除1線程A鎖,發(fā)現(xiàn)對業(yè)務(wù)A鎖是沒必要的。但是線程2會不會也會像剛才一樣產(chǎn)生線程死鎖呢?不會,因?yàn)榫€程2里并不會得到B鎖。
1線程———>獲得B鎖———>釋放B鎖
2線程-——————————>獲得A鎖————>釋放A鎖
3線程———>獲得B鎖———>獲得A鎖————>釋放A鎖————>釋放B鎖
問題是死鎖,但暴露了兩部分問題:
1.過早的認(rèn)為自己能控制好競爭關(guān)系,對線程間的競爭過早的做出了判斷
2.每多設(shè)計(jì)一個鎖就增加了一個競爭的因素,盡量小心,一個鎖就有可能是一個地雷,一不小心就可能導(dǎo)致嚴(yán)重的問題。
在《java并發(fā)編程實(shí)踐》這本書中介紹過LeftRightLock,詳細(xì)了解這個問題的朋友可以去查下這本書的第十章 避免活躍性危險(xiǎn)
此書極其詳細(xì)的介紹了LeftRightLock出現(xiàn)的可能,有可能是因?yàn)樽约壕帉懗绦虻氖韬鰧?dǎo)致,或者由于對鎖的認(rèn)識不足導(dǎo)致,諸多原因都能找到解釋。