为什么在调用另一个函数后lock_guard不会被破坏?

在我的代码库中,我有两个看起来像这样的函数:

void inside() {
  lock_guard<mutex> lock(LOCK);
  cout << "Finished inside" << endl;
}

void outside() {
  lock_guard<mutex> lock(LOCK);
  inside();
  cout << "Finished outside" << endl;
}

这会导致我的代码库中出现死锁,我觉得这很奇怪,因为我的印象是 lock_guard 在超出范围时会被破坏。我也尝试过使用 unique_lock,但得到了相同的结果。我能够解决它的唯一方法是在调用内部之前调用 unlock:

void outside() {
  LOCK.lock();
  // Do stuff
  LOCK.unlock();
  inside();
  cout << "Finished outside" << endl;
}

回答

我的印象是 lock_guard 在超出范围时会被破坏。

确实如此。问题是,您正在 2lock_guard个单独的范围内创建 2 个单独的对象。在 中outside(),您创建了一个在inside()运行时保持在范围内的对象。 inside()然后创建自己的对象,该对象在inside()退出时超出范围。对象 inoutside()保持在范围内,直到outside()退出。

话虽如此,请注意这std::mutex不是可重入的。mutex在调用线程已经拥有锁时尝试锁定 a是未定义的行为。您有 2 个lock_guard对象试图在同mutex一个线程中拥有相同的锁。这就是你陷入僵局的原因。您需要使用std::recursive_mutex来避免这种情况。一个线程可以拥有对 a 的多个锁recursive_mutex,只要它正确地将它们全部解锁。

否则,如果你真的想在进入之前outside()解锁,更干净(更安全)的处理方法是在 中引入一个新的范围,例如:mutexinside()outside()

void outside() {
  { // <--- starts a new scope here
  lock_guard<mutex> lock(LOCK);
  // Do stuff
  } // <-- ends the scope, destroying the lock_guard here
  inside();
  cout << "Finished outside" << endl;
}


以上是为什么在调用另一个函数后lock_guard不会被破坏?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>