unique_lock可以和recursive_mutex一起使用吗?

时间:2014-12-23 18:50:01

标签: c++ multithreading locking recursive-mutex

根据thisunique_lock可以通过声明std::unique_lock<std::recursive_mutex>来用于递归锁定,实际上编译得很好。

然而,从检查代码(gcc 4.8.2和4.9.0)看来,unique_lock并不遵循_Mutex.lock,而是实现了锁定方法本身:

  void
  lock()
  {
if (!_M_device)
  __throw_system_error(int(errc::operation_not_permitted));
else if (_M_owns)
  __throw_system_error(int(errc::resource_deadlock_would_occur));
else
  {
    _M_device->lock();
    _M_owns = true;
  }

显然,这可以防止互斥锁的递归锁定,并且实际上尝试以递归方式锁定抛出resource_deadlock_would_occur异常。

我在这里遗漏了什么,这是一个错误,还是unique_lock的文档错了?

TIA !!!

1 个答案:

答案 0 :(得分:19)

常见的错误是将mutexlock混淆。 mutex是一个可以在线程之间共享的对象(否则它将是无用的)。然而,锁本身不是一个线程安全的对象。它不应该在线程之间共享。它通常是堆栈上的本地对象。例如:

void foo()
{
     std::unique_lock<std::mutex> lk(mut);  // mut comes from some other scope
     // mut locked here
     // ...
}    // mut unlocked here

在上面的示例中,如果以递归方式调用foo(),则会有未定义的行为,因为您将递归锁定mut。在每次递归时,您会得到一个新的unique_lock。所以unique_lock不知道递归。如果您确实需要递归调用foo(),则需要使用递归互斥锁,例如:

void foo()
{
     std::unique_lock<std::recursive_mutex> lk(mut);  // mut comes from some other scope
     // mut locked here
     // ...
}    // mut unlocked here

所以:是的,您可以使用std::unique_lock<std::recursive_mutex>,是的,您的实施是正确的。