我正在调试死锁问题,调用堆栈显示线程正在等待某些事件。
代码使用临界区作为同步原语我认为这里存在一些问题。 此外,调试器指向一个其他线程拥有的关键部分,但锁定计数为-2。 根据我的理解,锁定计数> 0表示关键部分被一个或多个线程锁定。
那么我是否有可能在正确的关键部分寻找可能是死锁的罪魁祸首。
在哪些情况下,关键部分可能具有负锁定计数?
答案 0 :(得分:23)
注意:自Windows Server 2003(对于客户端操作系统this is Vista and newer),LockCount的含义已更改,-2是一个完全正常的值,通常在线程进入临界区而没有等待而没有其他线程时看到正在等待CS。见Displaying a Critical Section:
在Microsoft Windows Server 2003 Service Pack 1和更高版本的Windows中,LockCount字段的解析方式如下:
- 最低位显示锁定状态。如果该位为0,则临界区被锁定;如果为1,则关键部分未锁定。
- 下一位显示是否已为此锁定唤醒线程。如果该位为0,则该锁已被唤醒;如果是1,则没有线程被唤醒。
- 其余位是等待锁定的线程数的补码。
答案 1 :(得分:6)
我假设您正在讨论MFC中的CCriticalSection类。我认为你正在寻找合适的关键部分。我发现如果对Lock()函数的调用次数小于Unlock()调用次数,则临界区的锁定计数可能为负。我发现这通常发生在以下类型的代码中:
void f()
{
CSingleLock lock(&m_synchronizer, TRUE);
//Some logic here
m_synchronizer.Unlock();
}
乍一看,这段代码看起来非常安全。但请注意,我直接使用CCriticalSection的Unlock()方法而不是CSingleLock的Unlock()方法。现在发生的是当函数退出时,其析构函数中的CSingleLock再次调用临界区的Unlock()并且其锁定计数变为负数。在此之后,应用程序将处于糟糕的状态,并且奇怪的事情开始发生。如果您正在使用MFC关键部分,请检查此类问题。