pthread_cond_signal阻塞线程

时间:2014-04-11 04:51:05

标签: c multithreading pthreads

我有以下代码为最初作为共享变量count = 0的N个线程运行。每个变量在线程工作之前初始化。我试图只为MAX个线程执行代码的关键部分。

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()处被阻塞。我无法理解为什么会这样。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:3)

此代码有一个可能导致阻塞问题的弱点。 更准确地说,它不受所谓的虚假醒来的保护, 这意味着当没有信号通过调用pthread_cond_signal()或pthread_cond_broadcast()传递显式时,pthread_cond_wait()函数可能会返回。
因此,当计数变量小于或等于 MAX

时,代码中的以下行不保证线程唤醒
if(count>MAX){
    pthread_cond_wait(&count_threshold_cv, &count_mutex);
}

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

pthread_mutex_lock(&count_mutex);
count++;

如何保护代码免受虚假信号的侵害? pthread_cond_wait唤醒是检查谓词(count> MAX)的建议。 如果它仍然是假的,我们需要继续等待条件变量。 尝试通过将 if 语句更改为 while 语句来修复代码(并且,正如@alk所说,更改tmain()签名):

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

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

答案 1 :(得分:0)

您的代码阻止的原因是因为您在等待之前放置了count ++:

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所写。使用"如果"而不是"而#34;不会导致阻塞,而是导致太多线程同时运行;即使计数>唤醒的线程也开始工作MAX。

你需要"而#34;是pthread_cond_signal解除阻塞其中一个等待线程。但是,未阻塞的线程仍在等待互斥锁,并且它不一定要安排运行。当唤醒线程最终获取互斥锁并开始运行时,对pthread_cond_wait的调用返回。同时,在pthread_cond_signal和pthread_cond_wait的返回之间,其他线程可能拥有互斥锁。所以你必须再次检查条件,这是什么"而"确实

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

或者,您可以使用信号量来解决此问题。