我有这个课(简化):
// 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);
}
Run Code Online (Sandbox Code Playgroud)
如果我打电话来处理,我得到一个例外:
Microsoft C++ exception: std::system_error at memory location 0x006FF16C.
Run Code Online (Sandbox Code Playgroud)
锁定同一线程中的同一个锁会导致此异常.除了例外,我怎么能这样做?我想添加一个标志:
volatile bool alreadyLocked;
Run Code Online (Sandbox Code Playgroud)
改变内在:
void Thing::inner()
{
if (!alreadyLocked)
{
lock_guard<mutex> locking(lock);
alreadyLocked = true;
...something magic happens here...
alreadyLocked = false;
}
}
Run Code Online (Sandbox Code Playgroud)
然而,这感觉很脆弱......有没有正确的方法来做到这一点?
Vit*_*meo 12
首先,volatile变量不是线程安全的.您必须使用std::atomic<T>具有线程安全的变量.volatile与线程安全无关.
要解决您的问题,您可以使用std::recursive_mutex,可以从同一个线程多次锁定/解锁.
从cppreference:
调用线程拥有
recursive_mutex一段时间,该时间段在成功调用lock或启动时启动try_lock.在此期间,线程可能会对lock或进行额外调用try_lock.当线程进行匹配的解锁次数时,所有权期限结束.当一个线程拥有一个线程时
recursive_mutex,所有其他线程将阻塞(用于调用lock)或接收一个错误的返回值(fortry_lock)如果它们试图声明所有权recursive_mutex.
此外,请考虑重构您的代码,以便不需要两次锁定互斥锁.改进您的设计可能可以避免这个问题.