【问题标题】:Critical section negative lock count临界区负锁计数
【发布时间】:2009-06-26 07:32:30
【问题描述】:

我正在调试一个死锁问题,调用堆栈显示线程正在等待某些事件。

代码使用临界区作为同步原语我认为这里有一些问题。 此外,调试器指向某个其他线程拥有的临界区,但锁定计数为 -2。 根据我的理解 lock count>0 表示临界区被一个或多个线程锁定。

那么有没有可能我正在查看正确的关键部分,这可能是死锁的罪魁祸首。

在什么情况下临界区可以有负锁计数?

【问题讨论】:

标签: deadlock


【解决方案1】:

注意:由于 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,则没有线程被唤醒。
  • 其余位是等待锁的线程数的补码。

【讨论】:

  • 我在其他地方没有看到的精彩信息。帮助我解决了关键部分的一些奇怪行为。
  • 同上@mistiano 的评论。我不知道微软已经改变了 LockCount 在 Server 2003 及更高版本中的工作方式。该链接非常有用!
【解决方案2】:

我假设您正在谈论 MFC 中的 CCriticalSection 类。我认为您正在查看正确的关键部分。我发现如果对 Lock() 函数的调用次数少于 Unlock() 调用的次数,临界区的锁定计数可能会变为负数。我发现这通常发生在以下类型的代码中:

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

乍一看,这段代码看起来非常安全。但是,请注意我直接使用 CCriticalSection 的 Unlock() 方法而不是 CSingleLock 的 Unlock() 方法。现在发生的情况是,当函数退出时,其析构函数中的 CSingleLock 再次调用临界区的 Unlock(),其锁计数变为负数。在此之后,应用程序将处于糟糕的状态,并且开始发生奇怪的事情。如果您使用的是 MFC 关键部分,请检查此类问题。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-30
  • 1970-01-01
  • 2010-10-22
  • 1970-01-01
  • 2015-10-08
  • 1970-01-01
相关资源
最近更新 更多