我有这个类(简化):
// 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.
锁定同一线程中的同一锁会导致此异常。我怎么能做到这一点,没有例外?我想过添加一个标志:
volatile bool alreadyLocked;
将内部更改为:
void Thing::inner()
{
if (!alreadyLocked)
{
lock_guard<mutex> locking(lock);
alreadyLocked = true;
...something magic happens here...
alreadyLocked = false;
}
}
然而,这感觉很脆弱……有没有正确的方法来做到这一点?
原文由 imekon 发布,翻译遵循 CC BY-SA 4.0 许可协议
首先,
volatile
变量 不是线程安全的。您必须使用std::atomic<T>
才能拥有线程安全的变量。volatile
与线程安全无关。要解决您的问题,您可以使用
std::recursive_mutex
,可以从同一个线程多次锁定/解锁。来自 cppreference:
此外,请考虑重构您的代码,以便不需要两次锁定互斥锁。改进您的设计可能会避免这个问题。