記一次Java項目死鎖問題的排查思路


為了提升項目的響應速度,為用戶提供更好的體驗,原來的DAO使用的是JdbcTemplate,最近開發了一個有點類似Hibernate的組件,用來支持DAO對象的緩存。在數據插入和數據刪除時,多次使用鎖,有CLH自旋鎖ReentrantReadWriteLock讀寫鎖。設計的時候就覺得,多線程下邏輯有點復雜,很可能會發生死鎖,開發完成后進行測試,多線程同時進行查詢、插入和刪除操作,在測試程序執行了1個小時左右時,果然出現了請求未響應、響應處理慢的情況。

首先要做的是判斷問題是否由於死鎖導致:

請求沒有響應,處理慢,很有可能是處理線程被阻塞,或者是發生未捕獲的異常導致線程直接掛掉。開發時候有在自旋鎖上增加異常警告日志,如果自旋時間過長,則會打印日志。查看日志信息:

 果然打印了此日志,那么就有理由懷疑是死鎖導致的了。

接下來是定位死鎖發生的位置:

第一種可以使用jamp命令生成dump文件(以前發過的:使用mat工具分析內存占用 或百度用法)。因為我debug是用的idea,所以這里使用的是第二種方法:直接在idea中,分析dump。

接下來,找到請求處理線程,查看對應的調用棧信息。尤其要關注WAIT狀態和RUNNING狀態的(WAIT狀態大概率是讀寫鎖,而自旋鎖會占用CPU,RUNNING狀態下的也能是自旋鎖)。如下:

 

 然后像下圖這樣將所有由於鎖導致等待的線程的加鎖過程列出來,可以更清楚的分析是哪里可能發生死鎖,哪里可以去優化。

 

這里很容易就看出了是刪除和插入操作在並發時可能導致死鎖。修復代碼bug完善邏輯,死鎖的問題得以解決。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM