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