【问题标题】:Second thread doesn't wake up from cond_wait第二个线程没有从 cond_wait 唤醒
【发布时间】:2026-02-19 16:30:01
【问题描述】:

我们正在努力为 Game of life 找到一个好的同步。

因此,我们有一个打印机线程和当前两个线程来计算接下来要打印的新一代单元格。

计算线程只有在旧的已经打印出来的情况下才能开始计算新一代的游戏。

因此,我们使用打印机线程中的pthread_cond_signal(),它应该唤醒两个计算线程。

由于某种原因,只有一个线程在 pthread_cond_wait() 唤醒

我们已经尝试使用广播代替信号,但这没有任何效果。

这是我们的打印机线程所做的:

field -> printed = true;
//pthread_mutex_unlock(&(field -> print_mutex));
int status = pthread_cond_signal(&(field -> print_signal));

这是我们的计算线程所做的:

while(!field -> printed){
    printf("waiting for print_signal: %d\n", field -> printed);
    pthread_mutex_unlock(&(field -> print_mutex));
    pthread_cond_wait(&(field -> print_signal), &(field -> print_mutex));
    printf("print_signal received: %d\n", field -> printed);
}
printf("print_signal received2: %d\n", field -> printed);
pthread_mutex_unlock(&(field -> print_mutex));

然后计算线程进行计算并等待每个线程完成后再设置字段 -> 打印回 false。

我们觉得我们仍然没有真正了解如何正确使用互斥锁。

【问题讨论】:

    标签: c multithreading pthreads posix


    【解决方案1】:

    pthread_cond_signal() 正好发出所有线程等待的信号。

    来自 Linux 的 pthread_cond_signal 文档:

    pthread_cond_signal 重新启动正在等待条件变量 cond 的线程之一。

    要通知所有等待的线程,请使用pthread_cond_broadcast

    来自 Linux 的 pthread_cond_broadcast 文档:

    pthread_cond_broadcast 重新启动所有等待条件变量 cond 的线程。

    POSIX documentations 说:

    pthread_cond_broadcast() 函数将解除阻塞当前在指定条件变量 cond 上阻塞的所有线程。

    pthread_cond_signal() 函数应至少解除阻塞在指定条件变量 cond 上阻塞的线程之一(如果任何线程在 cond 上阻塞)。


    您还想在调用pthread_cond_wait()之前锁定互斥锁。线程进入等待状态的那一刻,互斥锁被隐式解锁。

    还要注意,在pthread_cond_wait() 返回后,互斥锁再次被锁定。

    要遵循这个概念,您可以将代码更改为如下所示:

    pthread_mutex_lock(&(field -> print_mutex));
    
    while (!field -> printed)
    {
      pthread_cond_wait(&(field -> print_signal), &(field -> print_mutex));
    }
    
    pthread_mutex_unlock(&(field -> print_mutex));
    

    还要确保在没有保护的情况下写入标志

    pthread_mutex_lock(&(field -> print_mutex));
    
    field -> printed = true;
    pthread_cond_signal(&(field -> print_signal));
    
    pthread_mutex_unlock(&(field -> print_mutex));
    

    最后采纳这个建议:在您的真实代码中,为 *all 那些pthread_*() 调用添加错误检查!


    而且^2 您确实确保条件和互斥锁已正确初始化,不是吗? ;-)

    【讨论】:

      最近更新 更多