2009-06-26 72 views
9

我正在調試死鎖問題,調用堆棧顯示線程正在等待某些事件。關鍵部分負鎖計數

代碼使用臨界區作爲同步原語我認爲這裏有一些問題。 此外,調試器正在指向某個其他線程擁有的關鍵部分,但鎖定計數爲-2。 根據我的理解,鎖計數> 0表示臨界區域被一個或多個線程鎖定。

所以有可能我正在看右邊的關鍵部分,這可能是死鎖的罪魁禍首。

在哪些情況下,臨界區域是否有負鎖定計數?

+0

Raymond Chen剛剛寫了一篇關於離開CS更多時間後果的文章。前三個評論值得一讀...... http://blogs.msdn.com/oldnewthing/archive/2009/06/19/9777996.aspx – eran 2009-06-26 08:17:43

回答

5

我假設你正在談論MFC中的CCriticalSection類。我認爲你正在看正確的關鍵部分。我發現如果Lock()函數的調用次數少於Unlock()調用的次數,那麼臨界區的鎖計數可能爲負數。我發現這通常發生在以下類型的代碼中:

void f() 
{ 
    CSingleLock lock(&m_synchronizer, TRUE); 
    //Some logic here 
    m_synchronizer.Unlock(); 
} 

乍一看,此代碼看起來非常安全。但是請注意,我直接使用CCriticalSection的Unlock()方法而不是CSingleLock的Unlock()方法。現在發生的情況是,當函數退出時,CSingleLock在其析構函數中再次調用臨界區的Unlock(),並且其鎖計數變爲負數。在此之後,應用程序將處於不良狀態,奇怪的事情開始發生。如果您正在使用MFC關鍵部分,請檢查是否存在此類問題。

+0

LockCount取決於您使用的Windows版本:http ://msdn.microsoft.com/en-us/library/ff541979.aspx – hfrmobile 2014-08-26 06:11:39

23

注意:從Windows Server 2003(對於客戶端操作系統this is Vista and newer),LockCount的含義已更改,-2是一個完全正常的值,通常在線程進入臨界區時沒有等待且沒有其他線程在等待CS。見Displaying a Critical Section

在Microsoft Windows Server 2003 Service Pack 1和更高版本的Windows中,鎖定計數字段如下解析:

  • 最低位顯示鎖定狀態。如果該位爲0,則關鍵部分被鎖定;如果它是1,則關鍵部分未被鎖定。
  • 下一位顯示線程是否已經爲此鎖喚醒。如果這個位是0,那麼一個線程已經被這個鎖喚醒;如果它是1,則沒有線程被喚醒。
  • 其餘位是等待鎖定的線程數的補碼。
+3

精彩的信息我沒有在別處看過。幫助我解決關鍵部分的一些奇怪的行爲。 – 2012-05-04 12:55:43