面對應用程序掛起時出現的間歇性多線程錯誤。當我暫停調試時,我看到該線程在鎖(_sync)子句上等待。所以問題是:線程鎖無限等待
- 當某些其他線程鎖定對象時,是否等待鎖定的唯一原因是?
- 如何知道什麼線程持有特定對象的鎖(在調試或運行時)?
我相信這不是一個「死鎖」,因爲死鎖意味着存在至少兩個對象和兩個線程,而在考慮代碼時只有一個同步對象。我認爲一些其他線程鎖定了對象並掛起,但我無法找到它是哪個線程。
面對應用程序掛起時出現的間歇性多線程錯誤。當我暫停調試時,我看到該線程在鎖(_sync)子句上等待。所以問題是:線程鎖無限等待
我相信這不是一個「死鎖」,因爲死鎖意味着存在至少兩個對象和兩個線程,而在考慮代碼時只有一個同步對象。我認爲一些其他線程鎖定了對象並掛起,但我無法找到它是哪個線程。
調試此方法的一種方法(沒有閃亮的VS2010提示)只能通過屬性/存取器訪問_sync。在那裏放置了一些診斷文本或斷點,你可以看到什麼線程想要同步和什麼時候。
除此之外,我不能給出任何合理的答案,沒有看到代碼。
我將記錄一些重要的調試技術。從Debug + Windows + Threads開始,它會顯示您的進程中正在運行的所有線程的列表。您可以將鼠標懸停在「位置」列上,您將看到一個工具提示,顯示該線程的堆棧跟蹤。這可以讓你快速地回到實際運行代碼的線程中。雙擊其中一個感興趣的部分,然後切換到Debug + Windows + Call Stack以獲得更持久的視圖。這可能會幫助您找到獲取該鎖的線程。
如果失敗,你可以找出哪個線程擁有鎖定對象。通過雙擊切換到阻止的線程,然後使用Debug + Windows + Memory + Memory 1.在地址框中鍵入「_sync」。右鍵單擊窗口並選擇「4字節整數」。從窗口左上角顯示的十六進制地址中減去4,然後在地址框中輸入該地址。或者單擊滾動條向上箭頭,查看第一行中的最後一個值。這是擁有鎖的線程的Thread.ManagedThreadId。請注意,這並不總是有效,對象中的這個字段也用於其他目的(例如GetHashCode)。
瞭解線程的託管標識現在讓您查看線程的「調試+ Windows +線程」窗口。但是,只有在VS2010中,早期版本纔會在此窗口中顯示線程的託管標識。對於這些,您需要添加一些顯示Thread.CurrentThread.ManagedThreadId值的跟蹤代碼。添加跟蹤代碼通常是解決線程問題的有用技術。然而,這個代碼改變了時間並且可能使線程問題消失,這是非常危險的。許多跟蹤監聽器也有一個隱含的鎖。
如果你的應用程序掛起0%的CPU,那麼你的死鎖問題> 0.999。如果它與100%的CPU掛起,那麼你有沒有終止繁忙循環。 –
嗯,不一定。例如,如果應用程序掛起0%CPU,則持有該鎖的線程可能僅在I/O上被阻塞。唯一可以肯定的是,100%的CPU可能意味着無限循環。 0%的CPU可以有很多不涉及死鎖的解釋。 – cdhowie
@cdhowie我假設最終IO將完成。 –