You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何C++ semaphore实现中同一mutex可被多线程多次锁定?

问题解析:为何多个线程都能“获取到同一个Mutex”

你的困惑源于对std::condition_variable::wait行为的误解——当线程调用wait时,它会自动释放持有的Mutex,被唤醒后又会重新获取Mutex。日志里的打印只是记录了线程曾经成功获取过Mutex的时刻,并非同一时刻多个线程持有Mutex。

具体流程拆解

以你的日志为例,逐个关键节点分析:

  1. 线程0调用acquire,成功锁定Mutex,打印0 aquired mutex in aquire,此时count_从2减到1,函数执行完毕,unique_lock析构,自动释放Mutex。
  2. 线程4获取到释放的Mutex,打印4 aquired mutex in aquire,count_从1减到0,函数执行完毕,释放Mutex。
  3. 线程3获取Mutex,打印3 aquired mutex in aquire,发现count_为0,进入cv_.wait(lck):
    • 这里wait会立即释放Mutex,让其他线程可以竞争获取。
  4. 线程2此时竞争到Mutex,打印2 aquired mutex in aquire,同样发现count_为0,调用wait释放Mutex。
  5. 后续线程5、1重复上述步骤:获取Mutex→打印日志→发现count为0→wait释放Mutex。

这些线程的“获取Mutex”操作是交替进行的,同一时刻永远只有一个线程持有Mutex,日志只是按时间顺序记录了每个线程成功获取Mutex的瞬间,并非同时持有。

额外代码优化建议

  • 调整release函数的执行顺序:当前代码先lck.unlock()再cv_.notify_one(),虽然功能正常,但更稳妥的做法是去掉手动unlock,让unique_lock在函数结束时自动释放Mutex,同时把cv_.notify_one()放在unlock之前(即利用unique_lock的作用域自动管理锁),避免因唤醒时机导致的潜在唤醒丢失。
  • 修复随机数生成问题:每个线程调用srand(id)会重置随机数种子,可能导致多个线程生成相同的等待时间,建议在main函数开头只调用一次srand(time(nullptr))。

内容的提问来源于stack exchange,提问作者Daniel Dobiński

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 07:57:36