这是一个普遍的问题。例如,当前有两个子线程已调用 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%肯定,所以如果有人可以详细说明,请随意这样做。
快速回答:
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%肯定,所以如果有人可以详细说明,请随意这样做。
我知道这是一个旧线程(没有双关语),但典型的实现是这样的:
条件变量将在其中包含当前处于睡眠状态的线程队列,等待它发出信号。
一个锁将有一个已经进入休眠状态的线程队列,因为它们试图获取它但是它被另一个线程持有。
cond_wait将正在运行的线程添加到条件变量的队列中,释放锁定并使其自身进入休眠状态。
cond_signal只是将一个休眠线程从条件变量的队列移动到锁的队列。
当正在运行的线程释放锁时,从锁的队列中移除一个休眠线程,锁的所有权被转移到该休眠线程,并且该休眠线被唤醒。
不要问我为什么规范说cond_signal可能会唤醒多个线程......