为什么在调用另一个函数后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;
}