是否保证pthread_cond_signal会唤醒等待的线程?

这是一个普遍的问题。 例如,当前有两个子线程调用了pthread_cond_wait(&cond1,&mutex) ,它们都在等待。 然后,父线程调用

 pthread_cond_signal(&cond1); pthread_cond_signal(&cond1); 

接下来,我的问题是,是否可以保证两个等待线程都会被唤醒?(假设第一个线程被唤醒,稍后在执行的某个阶段释放互斥,以便第二个线程可以获取它)。

我问这个问题的原因是,对于Unix系统级信号,信号(比如SIGCHLD )没有排队,因此如果连续传送多个相同类型的信号可能会丢失。 所以我想知道pthread_cond_signal是以不同方式实现的,这样如果调度程序碰巧让父线程连续两次发出信号,它们就不会丢失?

快速回答:

pthread_cond_signal()将唤醒至少一个在条件变量上被阻塞的线程 – 但不能保证更多(参考,使用pthread_cond_broadcast()来唤醒所有被阻塞的线程)。

从这里 :

pthread_cond_signal()调用取消阻塞在指定条件变量cond上阻塞的至少一个线程(如果在cond上阻塞了任何线程)。

pthread_cond_broadcast()调用取消阻止当前在指定条件变量cond上阻塞的所有线程。

答案越长:

因此,根据规范,我假设unblocking同步发生,也就是说,第一次调用pthread_cond_signal()解除阻塞的线程将被第二次调用pthread_cond_signal()视为未阻塞,因此另一个线程将被唤醒。

但是,我不知道你的具体pthread实现是否属于这种情况(目前glibc网站非常狡猾,因此无法访问代码来查看)。

可能还没有实现,但它在规范中的答案:

应该注意的是,最近对于pthread_cond_signal()pthread_cond_broadcast()确定在给定条件变量上实际阻塞了哪些线程,规范最近得到了一些改写,但我认为并非所有实现都已赶上。

关于这个主题的长时间讨论可以在这里找到,新规范是:

pthread_cond_broadcast()和pthread_cond_signal()函数将自动确定在指定的条件变量cond上阻塞哪些线程(如果有)。 此确定应在pthread_cond_broadcast()或pthread_cond_signal()调用期间的未指定时间发生。 然后,pthread_cond_broadcast()函数将解除所有这些线程的阻塞。 pthread_cond_signal()函数将取消阻塞这些线程中的至少一个。

因此,结论是:如果不是规范的专家解释器,我会说新文本支持同步发生这种情况的假设 – 因此两个连续调用pthread_cond_signal()并且两个被阻塞的线程可用,将唤醒两个线程。

我对此并不是100%肯定,所以如果有人可以详细说明,请随意这样做。

我知道这是一个旧线程(没有双关语),但典型的实现是这样的:

条件变量将在其中包含当前处于睡眠状态的线程队列,等待它发出信号。

一个锁将有一个已经进入hibernate状态的线程队列,因为它们试图获取它但是它被另一个线程持有。

cond_wait将正在运行的线程添加到条件变量的队列中,释放锁定并使其自身进入hibernate状态。

cond_signal只是将一个hibernate线程从条件变量的队列移动到锁的队列。

当正在运行的线程释放锁时,从锁的队列中移除一个hibernate线程,锁的所有权被转移到该hibernate线程,并且该hibernate线被唤醒。

不要问我为什么规范说cond_signal可能会唤醒多个线程……