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

Why lock_guard not get destructed after another function is called?

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

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,但得到了相同的结果。我能够解决它的唯一方法是在调用内部之前调用解锁:

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

I was under the impression that lock_guard gets destructed when it goes out of scope.

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

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

否则,如果您真的希望 outside() 在进入 inside() 之前解锁 mutex,更清洁(并且 更安全 )的方法在outside()中引入新作用域的handle,eg:

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;
}