繁体   English   中英

GCC C ++ 11条件变量等待内部

[英]GCC C++11 Condition Variable Wait Internals

我正在寻找一个我们的错误,一些凌乱的线程/条件变量类被更新为使用C ++ 11线程。 在狩猎过程中,我在GCC代码库中遇到了以下内容:

  template<typename _Lock>
  void
  wait(_Lock& __lock)
  {
    unique_lock<mutex> __my_lock(_M_mutex);
    _Unlock<_Lock> __unlock(__lock);
    // _M_mutex must be unlocked before re-locking __lock so move
    // ownership of _M_mutex lock to an object with shorter lifetime.
    unique_lock<mutex> __my_lock2(std::move(__my_lock));
    _M_cond.wait(__my_lock2);
  }

尽管有评论,但我很难理解移动构造函数的目的是__my_lock2。 为什么__my_lock在这里移动到__my_lock2?

这看起来不像condition_variable代码。 它看起来像condition_variable_any代码。 后者具有模板化等待功能。 前者没有。

N2406可以揭示你所看到的。 在N2406中, condition_variable_any被命名为gen_cond_var ,否则,类型是相同的。 本文描述了死锁情况,除非特别注意确保_M_mutex__lock以非常特定的顺序锁定和解锁,否则会实现死锁。

虽然您显示的代码和N2406上的代码不一样,但我强烈怀疑它们都是为了锁定和解锁这两个锁定而构建的,以避免N2406中描述的死锁。 如果没有进一步了解_Unlock的定义,我不能绝对肯定。 然而,一个强有力的线索是N2406中这个等待函数的最终评论:

}  // mut_.unlock(), external.lock()

即在锁定外部__lock之前必须解锁成员互斥锁。 通过移动__my_lock与范围小于的局部变量__unlock ,这是很有可能的正确排序

}  // _M_mutex.unlock(), __lock.lock()

已经实现了。 要理解为什么这个排序非常重要,你必须阅读N2406的相关部分(它可以防止死锁)。

该功能(我认为是std::condition_variable_any<_Lock>::wait )通过建立一个锁定顺序不变,避免僵局__lock必须取得前锁定_M_mutex 虽然这样做,它必须以某种方式仍然保证__lock而在内部条件变量等待没有保持_M_cond 请注意, _Unlock<_Lock>是RAII 解锁对象。 它通过在构造函数中解锁锁定析构函数来执行与通常的锁定防护相反的功能。 事件的必要顺序是:

  1. 获取__lockwait呼叫的前提条件)
  2. 获取_M_mutex (在__my_lock构造函数中)
  3. release __lock (在__unlock构造函数中)
  4. 原子地释放_M_mutex并等待_M_cond (发生在_M_cond.wait
  5. 唤醒时重新获取_M_mutex (也在_M_cond.wait
  6. 发布_M_mutex (在__my_lock2析构函数中)
  7. 重新获取__lock (在__unlock析构函数中)

__my_lock__my_lock2的移动是必要的,以便在__my_lock2之前销毁__unlock确保事件6发生在7而不是之后。

它似乎是重新排序__lock__my_lock变量的销毁。

调用应如下所示:

construct __my_lock // locks   _M_mutex
construct __unlock  // unlocks __lock
construct __my_lock2 // Does nothing as its a move.

_M_cond.wait(__my_lock2);

destroy __mylock2 // unlocks __M_mutex
destroy __unlock // locks __lock again
destroy __mylock // does nothing as its been moved

没有移动,订单就是

construct __my_lock // locks   _M_mutex
construct __unlock  // unlocks __lock

_M_cond.wait(__my_lock);

destroy __unlock // locks __lock
destroy __mylock // unlocks _M_mutex

这可能导致其他答案中提到的死锁

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM