2014-04-11 31 views
3

我有以下代码为count = 0的N个线程运行最初作为共享变量。在线程工作之前,每个变量都被初始化。我正在尝试仅执行最大线程数的代码的关键部分。pthread_cond_signal块线程

void *tmain(){ 
while(1){ 
    pthread_mutex_lock(&count_mutex); 
    count++; 
    if(count>MAX){ 
     pthread_cond_wait(&count_threshold_cv, &count_mutex); 
    } 
    pthread_mutex_unlock(&count_mutex); 
    /* 
    some code not associated with count_mutex or count_threshold_cv 
    */ 
    pthread_mutex_lock(&count_mutex); 
    count--; 
    pthread_cond_signal(&count_threshold_cv); 
    pthread_mutex_unlock(&count_mutex); 
} 
} 

但运行一段时间后,线程在pthread_cond_signal()处被阻塞。我无法理解为什么会出现这种情况。任何帮助表示赞赏。

+1

调用'pthread_cond_signal'不会在健康程序中死锁。您应该验证您正在操作的条件变量是否仍然存在并且未被损坏。另外,使用调试器来验证死锁时不同线程的确切位置,以及它们在那个时刻保持的锁定位置。 – ComicSansMS

+0

显示的代码看起来不错。如果不起作用,问题就出在其他地方。 Btw:如果将'tmain()'作为线程函数传递给'pthread_create()',则应声明为:void * tmain(void *)'。 – alk

+0

我加了[C]标签。如果你正在做[C++],请纠正这一点。 – alk

回答

3

此代码有一个弱点,可能会导致阻塞问题。 更确切地说,它不是保护,以防止所谓的虚假唤醒, 也就是说,当没有信号被调用交付明确的pthread_cond_wait()的函数或者返回调用pthread_cond_signal()或调用pthread_cond_broadcast()。
因此,从下面几行代码不保证该线程被唤醒时,计数变量小于或等于MAX

if(count>MAX){ 
    pthread_cond_wait(&count_threshold_cv, &count_mutex); 
} 

让我们看看当一个线程醒来会发生什么时计数仍然大于最大值: 之后立即解锁互斥量。 现在,其他线程可以进入临界会话,并增加计数变量超过预期:

pthread_mutex_lock(&count_mutex); 
count++; 

如何保护代码防止杂散信号? pthread_cond_wait唤醒是检查谓词(count> MAX)的建议。 如果它仍然是错误的,我们需要继续等待条件变量。 尝试通过改变如果语句来语句来修复您的代码(由@alk如说,改变tmain()签字):

while(count>MAX) 
{ 
    pthread_cond_wait(&count_threshold_cv, &count_mutex); 
} 

现在,如果虚假唤醒发生并且计数仍然大于MAX,那么流将再次等待条件变量。只有当唤醒伴随着谓词变化时,流才会逃离等待循环。

0

的原因,你的代码块是因为你把计数++等待前:

count++; 
if(count>MAX){ 
     pthread_cond_wait(&count_threshold_cv, &count_mutex); 
} 

相反,你应该写

while (count >= MAX) { 
     pthread_cond_wait(&count_threshold_cv, &count_mutex); 
} 
count++; 

的原因是,数应工作线程的数量。 线程只能在完成等待时递增计数。

另一方面,您的count变量计算工作线程的数量加上等待线程的数量。这个计数太大,导致条件计数> MAX是正确的哪些块。

你应该用MichaelGoren写的“while”替换“if”。使用“if”而不是“while”不会导致阻塞,而是会导致太多的线程同时运行;即使count> MAX,唤醒线程也开始工作。

您需要“while”的原因是pthread_cond_signal解锁了其中一个等待线程。然而,未阻塞的线程仍在等待互斥体,并且它不一定计划运行。当唤醒线程最终获得互斥并开始运行时,对pthread_cond_wait的调用返回。同时,在pthread_cond_signal和pthread_cond_wait的返回之间,其他线程可能拥有该互斥体。所以你必须再次检查这种情况,这是“一会儿”所做的。

另外,因为count ++现在在等待之后,条件变为count> = MAX而不是count> MAX。即使工人数量为MAX,您也应该等待。

或者,您可以使用这个问题的信号量。