我有两个条件变量:
CondVar1
CondVar2
在这样的两个线程中使用(伪代码):
// thread1 starts in 'waiting' mode, and then Thread2 signals
void Thread1()
{
CondVar1->Wait();
CondVar2->Signal();
}
void Thread2()
{
CondVar1->Signal();
CondVar2->Wait();
}
这会导致死锁吗?意思是,thread1等待,thread2信号,然后在thread2进入Wait()之前可以发送thread1信号,这意味着thread2永远不会返回?
由于
答案 0 :(得分:4)
您通常不会在条件变量上等待。常用模式是持有一个锁,检查一个变量,确定是否可以继续,如果你不能等待这个条件:
// pseudocode
void push( T data ) {
Guard<Mutex> lock( m_mutex ); // Hold a lock on the queue
while (m_queue.full()) // [1]
m_cond1.wait(lock); // Wait until a consumer leaves a slot for me to write
// insert data
m_cond2.signal_one(); // Signal consumers that might be waiting on an empty queue
}
有些注意事项:大多数库允许条件变量中的虚假唤醒。虽然可以实现避免虚假唤醒的条件变量,但操作的成本会更高,因此在继续({1}}循环[1]之前要求用户重新检查状态被认为是较小的罪恶。 )。
某些库,特别是C ++ 11,允许您传递谓词,并在内部实现循环:while
答案 1 :(得分:2)
有两种情况可能导致死锁:
Wait
的调用之前,可能会发出变量信号,因此信号会丢失。Wait
,从而发出尚未等待的线程2的信号。使用信令机制时,您应该按如下方式设计代码:
bool thread1Waits = true;
bool thread2Waits = true;
void Thread1()
{
while(thread1Waits) CondVar1->Wait();
thread2Waits = false;
CondVar2->Signal();
}
void Thread2()
{
thread1Waits = false;
CondVar1->Signal();
while(thread2Waits) CondVar2->Wait();
}
当然,这假设存在保护条件变量的锁,另外线程1在线程2之前运行。