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