`cond_broadcast` 是如何工作的?
Posted
技术标签:
【中文标题】`cond_broadcast` 是如何工作的?【英文标题】:How `cond_broadcast` works? 【发布时间】:2021-11-30 02:00:14 【问题描述】:我在理解互斥锁时遇到了问题,例如让我们考虑一下我书中的以下代码:
int students[2] = 0;
cond_t conds[2];
mutex_t global;
void onArrival(int faculty)
mutex_lock(&global);
int other = facolty ? 0:1;
while(students[other]>0) cond_wait(&conds[facolty],&global);
students[facolty]++;
mutex_unlock(&global);
void onLeave(int faculty)
mutex_lock(&global);
students[facolty]--;
int other = facolty ? 0:1;
cond_broadcast(&conds[other]);
mutex_unlock(&global);
cond_broadcast
会唤醒所有等待的线程,但真正的问题是持续多长时间?我的意思是,执行第 16 行可能会唤醒 1000 个线程,但是当他们尝试捕获互斥锁时,它们会失败,因为第 17 行尚未执行......
那么在这种情况下会发生什么?
线程重新进入睡眠状态,在执行第 17 行时没有人会唤醒?
或者,他们会忙着等待直到互斥锁被释放?
【问题讨论】:
请不要使用代码的图像。相反,将代码作为 text 粘贴到问题帖子中,并对其进行适当的格式化。这就是堆栈溢出的工作方式。另请参阅How to Ask。 @Tsyvarev Done,你现在能帮我吗? 这能回答你的问题吗? Which thread owns the associated mutex after pthread_cond_broadcast?cond_broadcast
将等待线程转换为状态,类似于mutex_lock
调用中的一个。也就是说,如果互斥锁被锁定,那么所有的等待者都保持在等待状态,但是那个时候他们将等待mutex,而不是condition。
【参考方案1】:
cond_broadcast
将唤醒所有等待的线程,但真正的 问题是多久?我的意思是第 16 行可能会发生 已执行,唤醒了 1000 个线程
是的,从某种意义上说,它将他们从等待 CV 转变为争夺互斥锁。在他们成功获取互斥锁之前,他们实际上可能有资格也可能没有资格调度或接收任何 CPU 时间(感谢@DavidSchwartz 的澄清)。
但是当他们试图抓住 mutex 他们失败了,因为第 17 行还没有执行......
没有。线程不会无法获取互斥锁,至少不是因为这个原因。他们可能只需要等待才能获得它。
那么在这种情况下会发生什么?
线程重新进入睡眠状态,在执行第 17 行时没有人会唤醒?
或者,他们会忙着等待直到互斥锁被释放?
这取决于互斥锁的实现,但一般来说,线程会尝试获取互斥锁block,直到它们可以这样做。他们不会忙着等待。无论他们是显式获取互斥锁,还是在等待 CV 被唤醒后获取互斥锁,都是完全相同的。
请注意,任何阻塞尝试获取互斥锁的线程与等待来自 CV 的信号时的状态不同。他们正在争夺互斥锁,而之前没有,并且在继续之前他们不需要来自 CV 的另一个信号。
这是一个有点精明的问题,因为这里确实考虑了现实生活中的性能。使用允许向 CV 发送信号或广播而无需锁定相关互斥锁的 CV 实现,例如pthreads
,在互斥锁解锁的情况下执行此操作会更有效,这样至少一个线程可以立即继续,而不是醒来,然后立即再次阻塞。但这是一个效率问题,而不是语义问题。
【讨论】:
谢谢你,@DavidSchwartz。我已将您的说明的一个版本纳入此答案。 你有一个明显的矛盾:“但一般来说,线程试图获取互斥块直到他们可以这样做。他们不会忙着等待。” 这有什么矛盾的,@algo?以上是关于`cond_broadcast` 是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章