2013-03-18 40 views
11

这是一个普遍的问题。例如,目前有两个子线程调用pthread_cond_wait(&cond1,&mutex),它们都在等待。然后,父线程调用保证pthread_cond_signal会唤醒等待线程吗?

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

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

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

回答

12

快速答案:

pthread_cond_signal()会醒来至少一个被阻止的条件变量的螺纹的 - 但更重要的是,不能保证(供参考,使用pthread_cond_broadcast()唤醒所有被阻塞的线程)。

here

的调用pthread_cond_signal()调用放开被阻挡在指定条件变量COND(如果有的话 线程被阻塞上COND),该螺纹 中的至少一个。

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

较长的答案:

因此,根据该规范,我推测解锁同步发生的,也就是说,已被解封第一调用pthread_cond_signal()线程会被第二次调用pthread_cond_signal()解除阻塞,从而另一个线程将被唤醒。但是,我不知道你的特定pthread实现是否是这种情况(并且glibc网站目前非常不友善,所以无法访问代码来查看)。但是,我不知道这是否适用于特定的pthread实现。

的可能,尚未实现的,但是,它 - 是 - 在最规范的答案:

应该指出虽然,该规范最近得到了稍微改写关于如何pthread_cond_signal()pthread_cond_broadcast()确定哪些线程实际上在给定的条件变量上被阻塞,但我认为并非所有的实现都已经赶上了。

关于这个问题的长时间的讨论可以发现here,与新的规格之中:

的调用pthread_cond_broadcast()和调用pthread_cond_signal()函数 须原子确定哪些线程,如果有的话,就阻止 指定的条件变量cond。该确定 应在 pthread_cond_broadcast()或pthread_cond_signal()调用期间的非指定时间发生。 然后pthread_cond_broadcast()函数将取消阻塞这些线程的所有 。 pthread_cond_signal()函数至少应在 这些线程之一解除阻塞。

所以,结论是: 而不规范的专家解释,我想说的是,新的文本支持此同步发生的假设 - 这样有两个可用阻塞的线程连续两次调用pthread_cond_signal(),将唤醒两个线程。

我不是这个100%肯定的,所以如果有人能详细,你这样做。

+1

即使有一个线程等待(在OPS为两个),如果互斥锁定在信号的时间没有人在任何地方发布,直到它被释放。更好的问题是,如果你锁定信号 - 解锁信号,那么当互斥锁最终解锁并且每个都可以获得它,释放它并允许* other *线程同样的自由时,它们都会收到信号*然后*。我真的不知道。 – WhozCraig 2013-03-18 20:41:29

+0

我认为@WhozCraig已经提出了我的问题。我想另外一个问题是,鉴于我在原文中所说的话,是否意味着两个线程最终都会被唤醒(如果互斥锁被正确解锁),因为父母已经调用了pthread_cond_signal两次? – protossor 2013-03-18 20:45:39

+0

啊是的 - 我有点太快回答我猜;)我会更新上述... – sonicwave 2013-03-18 20:47:24

0

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

条件变量会在它这是目前睡着的线程队列,等待它来获得信号。

锁将已投入睡觉,因为他们试图获取它,但它被另一个线程持有的线程队列。

cond_wait增加了运行的线程条件变量的队列,释放锁,并提出自己睡觉。

cond_signal简单地移动一个睡眠线程从状态变量的队列到锁的队列中。

当正在运行的线程释放锁,一个沉睡的线程从锁的队列中删除,锁的所有权转移到休眠线程,而休眠线程被唤醒。

不要问我为什么规范说一个cond_signal可能醒来一个多线程的...