multithreading - 调用 condition_all() 时,多个线程(正在等待条件变量)如何获取相关锁?
问题描述
从理论上讲,等待线程(比如说 Thread_1)首先获取一个互斥体,然后通过调用 wait() 等待条件变量。对 wait() 的调用会立即解锁互斥锁。当另一个线程(比如说 Thread_2)调用 notify() 时,等待线程 (Thread_1) 被唤醒,并且在 wait(..) 调用返回之前,同一个互斥锁被锁定。
现在假设多个线程在给定时间等待一个条件变量(比如说 Thread_1、Thread_2 和 Thread_3)。现在另一个线程 (Thread_4) 调用 notify_all(),它将通知正在等待条件变量的所有 3 个线程。当他们被唤醒时,他们三个如何才能锁定互斥锁,这应该在 wait(...) 调用返回之前发生?只有一个线程(3 个等待线程中的)可以获取互斥锁。那么 notify_all() 的目的是什么,如果它只能解锁一个线程呢?notify() 和 notify_all() 之间的结果(从等待线程的角度来看)有什么区别?
解决方案
他们三个如何锁定互斥锁?
他们像往常一样一次锁定一个。
一个wait(...)
函数可以这样实现:
def wait(cond_var, mutex):
tricky_internal_wait(cond_var, mutex)
lock(mutex)
该tricky_internal_wait(c,m)
函数将自动解锁互斥锁并阻塞与 关联的队列上的调用线程cond_var
,但没有理由说明lock(mutex)
它末尾的调用需要与普通的lock(mutex)
.
当在cond_var
上面的示例中通知 时,线程将唤醒,然后它会调用lock(mutex)
,然后如果其他线程已经锁定了互斥锁,操作系统将阻塞与 关联的队列中的调用者mutex
。调用者在从wait()
调用中返回之前不能从调用中返回lock()
,并且lock()
在互斥体可用并且调用者获取它之前它不能从调用中返回。就像lock()
往常一样。
一个实际的实现可能会更有效地做事情:如果线程已经被其他线程使用,wait(c,m)
它可能会将线程直接从cond_var
队列移动到mutex
队列,而不会唤醒线程。mutex
那么 notify_all() 的目的是什么,如果它只能解锁一个线程呢?
它不会只解锁一个。它解锁了所有这些,...
...一次一个。
假设一些线程 T 调用notify_all(cond_var)
,而线程 X、Y 和 Z 都在等待 中的条件foobar()
:
def foobar():
lock(mutex)
while condition_is_not_satisfied():
wait(cond_var, mutex)
do_some_thing_that_requires_condition_to_be_satisfied()
unlock(mutex)
也许线程 Z 将是第一个从wait()
调用中返回的。它会再次检查条件是否真的满足,然后它会做这件事,然后它会解锁mutex
并从foobar()
.
在线程 Z 解锁互斥锁并返回之前,线程 X 和 Y 将无法从wait()
调用中返回。
也许在 Z 解锁互斥体之后,从 wait() 返回的下一个将是 X。然后 X 将检查条件是否满足。也许 Z 的动作意味着条件不再满足。在这种情况下,X 将wait()
再次调用,并且wait()
调用将释放互斥锁。或者,可能条件仍然满足,X 将执行此操作,并显式解锁互斥锁并从foobar()
.
无论哪种方式,线程 X 将释放互斥锁,然后线程 Y 将能够从wait()
调用中返回......
……就这样。
推荐阅读
- javascript - 如何使循环遍历枚举的每个项目并验证每个重复是否在正确的枚举中
- mysql - MySQL 检查约束违规
- android - 配置项目“:CordovaLib”时出现问题。> 无法解析配置 ':CordovaLib:classpath' 的所有工件:Ionic3
- sql - Impala 如何以分布式方式实现 GroupBy 扩展(CUBE、ROLLUP 和 GROUPING SETS)?
- react-native - 如何从外部电子邮件链接打开 React 本机应用程序
- python - 从 Microsoft Graph API 获取 414 请求 Uri 太长
- firebase - 如何解决flutter中的“URI目标不存在包:flutter_facebook_login/flutter_facebook_login.dart”?
- java - 无法通过 okhttp 在烧瓶中填充 request.files
- apache - Gatsby 网站不会在 debian VPS 上显示
- python - 在 Python 中删除输出中的多余行