2009-06-26 42 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