我想使用C++ 11 std :: condition_variable,但是當我嘗試鎖定與第二個線程關聯的unique_lock時,我得到一個異常「避免資源死鎖」。創建它的線程可以鎖定和解鎖它,但不是第二個線程,儘管我非常確定unique_lock不應該在第二個線程試圖鎖定它的時候鎖定。鎖定C++ 11 std :: unique_lock導致死鎖異常
FWIW我在Linux中使用gcc 4.8.1,使用-std = gnu ++ 11。
我已經在condition_variable,unique_lock和mutex周圍編寫了一個包裝類,因此我的代碼中沒有其他東西可以直接訪問它們。注意使用std :: defer_lock,我已經陷入了陷阱:-)。
class Cond {
private:
std::condition_variable cCond;
std::mutex cMutex;
std::unique_lock<std::mutex> cULock;
public:
Cond() : cULock(cMutex, std::defer_lock)
{}
void wait()
{
std::ostringstream id;
id << std::this_thread::get_id();
H_LOG_D("Cond %p waiting in thread %s", this, id.str().c_str());
cCond.wait(cULock);
H_LOG_D("Cond %p woke up in thread %s", this, id.str().c_str());
}
// Returns false on timeout
bool waitTimeout(unsigned int ms)
{
std::ostringstream id;
id << std::this_thread::get_id();
H_LOG_D("Cond %p waiting (timed) in thread %s", this, id.str().c_str());
bool result = cCond.wait_for(cULock, std::chrono::milliseconds(ms))
== std::cv_status::no_timeout;
H_LOG_D("Cond %p woke up in thread %s", this, id.str().c_str());
return result;
}
void notify()
{
cCond.notify_one();
}
void notifyAll()
{
cCond.notify_all();
}
void lock()
{
std::ostringstream id;
id << std::this_thread::get_id();
H_LOG_D("Locking Cond %p in thread %s", this, id.str().c_str());
cULock.lock();
}
void release()
{
std::ostringstream id;
id << std::this_thread::get_id();
H_LOG_D("Releasing Cond %p in thread %s", this, id.str().c_str());
cULock.unlock();
}
};
我的主線程創建了一個RenderContext,它有一個與它關聯的線程。從主線程的角度來看,它使用Cond來指示渲染線程執行一個動作,並且還可以在COnd上等待渲染線程完成該動作。渲染線程在Cond上等待主線程發送渲染請求,並使用相同的Cond告訴主線程完成了必要的操作。我得到的錯誤發生在渲染線程試圖鎖定Cond以檢查/等待渲染請求時,此時它不應該被鎖定(因爲主線程正在等待它),更不用說由同一個線程。下面是輸出:
DEBUG: Created window
DEBUG: OpenGL 3.0 Mesa 9.1.4, GLSL 1.30
DEBUG: setScreen locking from thread 140564696819520
DEBUG: Locking Cond 0x13ec1e0 in thread 140564696819520
DEBUG: Releasing Cond 0x13ec1e0 in thread 140564696819520
DEBUG: Entering GLFW main loop
DEBUG: requestRender locking from thread 140564696819520
DEBUG: Locking Cond 0x13ec1e0 in thread 140564696819520
DEBUG: requestRender waiting
DEBUG: Cond 0x13ec1e0 waiting in thread 140564696819520
DEBUG: Running thread 'RenderThread' with id 140564575180544
DEBUG: render thread::run locking from thread 140564575180544
DEBUG: Locking Cond 0x13ec1e0 in thread 140564575180544
terminate called after throwing an instance of 'std::system_error'
what(): Resource deadlock avoided
說實話,我真的不明白一個unique_lock是什麼,爲什麼需要condition_variable一個,而不是直接使用互斥體,所以這可能是問題的原因。我無法在網上找到很好的解釋。
不要爲所有線程使用相同的'unique_lock',這並不意味着它會被使用。將它們用作塊範圍內的RAII對象,而不是類成員。這樣,每個調用函數的線程都將擁有自己的實例。另外,介紹虛假喚醒。 – syam
我看到了,所以想要等待或發送通知的每個上下文應該使用它自己的unique_lock,但是所有共享相同的互斥量? – realh
只需等待,不發送('cv.notify()'不需要鎖)。但是,否則,是的。我會盡量整理一個答案,告訴你如何正確使用這一點,現在我只是有點忙。 – syam