我想使用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