为何此Condvar的wait与notify用法不会产生死锁?
关于Condvar示例中竞态情况的解释
你提的这个问题完全合理,乍一看好像确实会出现死锁,但其实Condvar的wait方法藏着关键机制,完美解决了这个问题,咱们来仔细拆解:
首先,先明确你担心的场景:主线程先执行到标记#2处,成功获取Mutex的锁,这时候子线程才开始运行,在#1处尝试获取锁会被阻塞,看起来主线程会一直卡在while !*started的循环里,子线程又拿不到锁修改值,陷入死循环。
但实际上,当主线程调用cvar.wait(started).unwrap()的时候,发生了两个原子性的操作:
- 自动释放当前持有的
Mutex锁 - 让当前线程进入等待状态,直到收到Condvar的通知
这就意味着,主线程一旦进入wait,锁就被释放了,子线程立刻就能拿到#1处的锁,修改*started为true,然后调用cvar.notify_one()发送通知。
当主线程收到通知后,会重新获取Mutex锁,然后回到while循环的判断条件,这时候*started已经是true了,循环就会正常退出。
另外还要补充一点:官方示例用while而不是if判断条件,是因为Condvar存在虚假唤醒的可能——线程可能在没有收到notify的情况下被唤醒。用while循环可以确保每次唤醒后都重新检查条件,避免因为虚假唤醒导致程序逻辑出错。
咱们再把两种可能的执行流程理清楚:
- 场景A:子线程先运行,拿到#1的锁,修改
started为true并通知Condvar,之后主线程拿到#2的锁,检查*started直接为true,跳过循环。 - 场景B:主线程先拿到#2的锁,发现
*started为false,调用wait释放锁,子线程拿到#1的锁修改值并通知,主线程被唤醒重新拿锁,检查条件满足退出循环。
两种场景下程序都能正常运行,完全不会出现你担心的死锁问题~
内容的提问来源于stack exchange,提问作者Wynell
相关产品推荐
相关产品推荐

