为什么 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;
}
在我的代码库中,我有两个看起来像这样的函数:
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;
}