最近寫服務,經常是單進程,多線程的,加了各種鎖,很擔心出現死鎖問題,專門學習了一下死鎖問題的診斷。
死鎖 (deallocks): 是指兩個或兩個以上的進程(線程)在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或 系統產生了死鎖,這些永遠在互相等待的進程(線程)稱為死鎖進程(線程)。 由於資源占用是互斥的,當某個進程提出申請資源后,使得有關進程(線程)在無外力協助下,永遠分配不到必需的資源而無法繼續運行,這就產生了一種特殊現象 死鎖。
一種交叉持鎖死鎖的情形,此時執行程序中兩個或多個線程發生永久堵塞(等待),每個線程都在等待被其它線程占用並堵塞了的資源。例如,如果線程 1 鎖住了記錄 A 並等待記錄 B,而線程 2 鎖住了記錄 B 並等待記錄 A,這樣兩個線程就發生了死鎖現象。在計算機系統中 , 如果系統的資源分配策略不當,更常見的可能是程序員寫的程序有錯誤等,則會導致進程因競爭資源不當而產生死鎖的現象。
產生死鎖的四個必要條件
(1) 互斥條件:一個資源每次只能被一個進程(線程)使用。
(2) 請求與保持條件:一個進程(線程)因請求資源而阻塞時,對已獲得的資源保持不放。
(3) 不剝奪條件 : 此進程(線程)已獲得的資源,在末使用完之前,不能強行剝奪。
(4) 循環等待條件 : 多個進程(線程)之間形成一種頭尾相接的循環等待資源關系。
pstack 在 Linux 平台上的簡單介紹
pstack 是 Linux(比如 Red Hat Linux 系統、Ubuntu Linux 系統等)下一個很有用的工具,它的功能是打印輸出此進程的堆棧信息。可以輸出所有線程的調用關系棧。
gdb 在 Linux 平台上的簡單介紹
GDB 是 GNU 開源組織發布的一個強大的 UNIX 下的程序調試工具。Linux 系統中包含了 GNU 調試程序 gdb,它是一個用來調試 C 和 C++ 程序的調試器。可以使程序開發者在程序運行時觀察程序的內部結構和內存的使用情況 .
gdb 所提供的一些主要功能如下所示:
1 運行程序,設置能影響程序運行的參數和環境 ;
2 控制程序在指定的條件下停止運行;
3 當程序停止時,可以檢查程序的狀態;
4 當程序 crash 時,可以檢查 core 文件;
5 可以修改程序的錯誤,並重新運行程序;
6 可以動態監視程序中變量的值;
7 可以單步執行代碼,觀察程序的運行狀態。
示例:
我所做的項目中一個服務進程有45個線程並行運行。發現程序異常,可以通過
pstack 進程號 查看各個線程的堆棧信息。
需要連續多次執行 pstack 進程號 命令。 查看每個線程的函數調用關系的堆棧,進行分析。當進程吊死的時候,多次使用,死鎖的線程將一直處於等鎖的狀態,確定某些線程一直沒有變化,一直處於等鎖的狀態。那么這些線程很可能是死鎖了。如果懷疑哪些線程發生死鎖了,可以采用gdb 進一步attach線程並進行分析。
如上兩個圖,我們發現線程18和線程1,2,3,都處於等鎖狀態,等待相同的鎖,連續多次觀察都是這個現象。
因此: 執行命令 gdb attach 9368(進程號) 進入gdb調試終端。
運行:(gdb) info thread
系統調用可能導致死鎖,
syslog
system
內存釋放
exit