2009-07-16 63 views
44

我正在学习pthread和等待条件。至于我可以告诉一个典型的等待线程是这样的:Pthread和等待条件

pthread_mutex_lock(&m); 
while(!condition) 
    pthread_cond_wait(&cond, &m); 
// Thread stuff here 
pthread_mutex_unlock(&m); 

我不能理解的是,为什么线while(!condition)非常必要,即使我用pthread_cond_signal()来唤醒线程。

我可以理解,如果我用pthread_cond_broadcast()我需要测试的条件,因为我醒来所有等待线程,其中一个可以解锁互斥(因此转移执行到另一个唤醒之前再次使病情假线程不应该在这一点执行)。 但是,如果我使用pthread_cond_signal()我醒来只是一个线程所以条件必须是真实的。所以代码可能是这样的:

pthread_mutex_lock(&m); 
pthread_cond_wait(&cond, &m); 
// Thread stuff here 
pthread_mutex_unlock(&m); 

我读了一些关于可能发生的虚假信号。这(并且仅此)是原因吗?为什么我应该有虚假singnals?或者还有别的东西我没有得到?

我假设的信号代码是这样的:

pthread_mutex_lock(&m); 
condition = true; 
pthread_cond_signal(&cond); // Should wake up *one* thread 
pthread_mutex_unlock(&m); 

回答

43

您应该将pthread_cond_wait放在while循环中的真正原因不是因为虚假唤醒。即使您的条件变量没有虚假唤醒,您仍然需要循环来捕获常见类型的错误。为什么?考虑如果多个线程等待在相同条件下可能发生的事情:

Thread 1       Thread 2   Thread 3 
check condition (fails) 
(in cond_wait) unlock mutex 
(in cond_wait) wait 
           lock mutex 
           set condition 
           signal condvar 
           unlock mutex 
                lock mutex 
                check condition (succeeds) 
                do stuff 
                unset condition 
                unlock mutex 
(in cond_wait) wake up 
(in cond_wait) lock mutex 
<thread is awake, but condition 
is unset> 

的这里的问题是,线程必须等待之前释放互斥体,可能允许另一个线程来“窃取”无论该线程在等待。除非保证只有一个线程可以等待该条件,否则在线程唤醒时假定条件有效是不正确的。

15

假设你不检查的条件。那么通常你无法避免以下坏事发生了(至少,你无法避免它的一行代码):

Sender        Receiver 
locks mutex 
sets condition 
signals condvar, but nothing 
    is waiting so has no effect 
releases mutex 
            locks mutex 
            waits. Forever. 

当然你的第二个代码示例可避免此做:

pthread_mutex_lock(&m); 
if (!condition) pthread_cond_wait(&cond, &m); 
// Thread stuff here 
pthread_mutex_unlock(&m); 

那么肯定会出现这样的情况,如果只有最多一个接收者,并且如果cond_signal是唯一能够唤醒它的东西,那么它只会在条件设置时醒来,因此不需要循环。 nos涵盖了为什么第二个“如果”不是真的。

+0

我明白了,所以由于逻辑原因(无尽的等待)需要“if”,但由于实现问题(虚假信号),实际需要一段时间。 – Emiliano 2009-07-16 11:40:24

+0

是的,当我第一次使用pthreads库时,我问了同样的问题。我省略了检查状态变量,并且在等待发生之前我的程序会发出信号。这是等待/信号功能的全部要点。等待并发出一些互斥保护的内存状态变化信号。 – 2011-03-25 15:09:46