Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
pthread_cond_信号阻塞线程_C_Multithreading_Pthreads - Fatal编程技术网

pthread_cond_信号阻塞线程

pthread_cond_信号阻塞线程,c,multithreading,pthreads,C,Multithreading,Pthreads,以下代码最初作为共享变量为N个count=0的线程运行。每个变量都在线程工作之前初始化。我试图只为最大线程数执行代码的关键部分 void *tmain(){ while(1){ pthread_mutex_lock(&count_mutex); count++; if(count>MAX){ pthread_cond_wait(&count_threshold_cv, &count_mutex); } p

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

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()处被阻塞。我无法理解为什么会发生这种情况。非常感谢您的帮助。

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

if(count>MAX){
    pthread_cond_wait(&count_threshold_cv, &count_mutex);
}
让我们看看当一个线程在计数仍然大于MAX时被唤醒时会发生什么: 紧接着,互斥锁被解锁。 现在,其他线程可以进入关键会话,并将count变量的增量超过预期值:

pthread_mutex_lock(&count_mutex);
count++;
如何保护代码不受虚假信号的影响? 建议使用pthread_cond_wait唤醒来检查谓词(count>MAX)。 如果仍然为false,则需要继续等待条件变量。 尝试通过将if语句更改为while语句来修复代码(并且,如@alk所述,更改tmain()签名):

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

代码阻塞的原因是您将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应该是工作线程的数量。 线程只能在等待完成时增加计数

另一方面,count变量计算工作线程数加上等待线程数。此计数太大,导致条件计数>最大值为true,从而导致阻塞

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

需要“while”的原因是pthread_cond_信号解除了其中一个等待线程的阻塞。但是,未阻塞的线程仍在等待互斥锁,并且不一定计划运行互斥锁。当被唤醒的线程最终获取互斥体并开始运行时,对pthread_cond_wait的调用将返回。同时,在pthread_cond_信号和pthread_cond_wait返回之间,其他线程可能拥有互斥锁。因此,您必须再次检查条件,“while”就是这样做的

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


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

调用
pthread\u cond\u signal
不能在正常程序中死锁。您应该验证正在操作的条件变量是否仍然有效,并且没有损坏。另外,使用调试器来验证在死锁发生时不同线程被阻塞的确切位置,以及它们在该点上持有的锁。如果它不起作用,问题就在别处。顺便说一句:如果
tmain()
作为线程函数传递给
pthread\u create()
,则应声明:
void*tmain(void*)
。我添加了[C]标记。如果您正在使用[C++],请更正此问题。
while (count >= MAX) {
        pthread_cond_wait(&count_threshold_cv, &count_mutex);
}
count++;