我有这个类(简化):
// thing.h
#include <mutex>
class Thing
{
public:
void process();
void inner();
private:
std::mutex lock;
};
// thing.cpp
#include "Thing.h"
using namespace std;
void Thing::process()
{
lock_guard<mutex> locking(lock);
inner();
}
void Thing::inner()
{
lock_guard<mutex> locking(lock);
}
如果我调用进程,我会得到一个异常:
Microsoft C++ exception: std::system_error at memory location 0x006FF16C.
在同一线程中锁定同一锁会导致此异常。我怎么能毫无异常(exception)地做到这一点?我考虑过添加一个标志:
volatile bool alreadyLocked;
内部更改为:
void Thing::inner()
{
if (!alreadyLocked)
{
lock_guard<mutex> locking(lock);
alreadyLocked = true;
...something magic happens here...
alreadyLocked = false;
}
}
但是这感觉很脆弱......有没有正确的方法来做到这一点?
最佳答案
首先,volatile
变量不是线程安全的。您必须使用 std::atomic<T>
拥有线程安全的变量。 volatile
与线程安全无关。
要解决您的问题,您可以使用 std::recursive_mutex
,可以从同一个线程多次锁定/解锁。
来自cppreference:
A calling thread owns a
recursive_mutex
for a period of time that starts when it successfully calls eitherlock
ortry_lock
. During this period, the thread may make additional calls tolock
ortry_lock
. The period of ownership ends when the thread makes a matching number of calls to unlock.When a thread owns a
recursive_mutex
, all other threads will block (for calls tolock
) or receive a false return value (fortry_lock
) if they attempt to claim ownership of therecursive_mutex
.
此外,请考虑重构您的代码,以便不需要两次锁定互斥量。改进您的设计可能会避免这个问题。
关于c++ - 如何在同一个线程上使用同一个互斥锁锁定两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46767423/