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

同一线程持有std::unique_lock与shared_lock为何未触发锁错误?

问题核心原因

你对std::shared_mutex的规则理解存在一个关键偏差:同线程在持有排他锁时再次申请同个shared_mutex的共享锁,属于标准明确规定的未定义行为,C++标准不要求实现必须拦截、报错或者阻塞这类错误操作。

具体说明

  • 首先,std::shared_mutex是非递归性质的读写锁,它的语义约定确实是「同一时刻最多只能有一个线程持有排他写锁,持有写锁时任何线程(包括当前持锁线程)都不能再持有共享读锁;多线程可以同时持有共享读锁,持读锁时任何线程都不能申请到写锁」。但这个语义约束只针对跨线程的正确使用场景,对于同线程违规重复/混合加锁的错误用法,标准没有强制要求实现做正确性校验。
  • 你所用的g++ 9.4.0搭配的libstdc++实现中,std::shared_mutex的加锁逻辑没有做「当前线程是否已经持有另一种类型锁」的校验:只要加锁操作能进入内部临界区修改锁计数,就会直接标记加锁成功,不会检查持锁线程身份。这才会出现你观察到的、同一线程同时持有unique_lock和shared_lock的现象——这不是锁本身支持这种操作,只是实现没有拦住你的错误用法。
  • 这种表现完全不具备可移植性:换用其他标准库实现(比如libc++、MSVC STL)、甚至只是调整g版本、编译优化等级,同一段代码可能出现死锁、触发断言崩溃、运行结果异常等任意表现,所有这些都符合C标准对未定义行为的规定。
  • 你可以通过跨线程测试验证锁的正常语义:在当前线程持有排他写锁时,启动另一个线程尝试申请共享读锁,新线程会正常阻塞直到写锁释放,说明锁的跨线程互斥逻辑是正常工作的,只是同线程的违规操作没有被检测拦截。

注:哪怕是同线程重复申请同类型的锁(比如已经持有unique_lock再申请第二个unique_lock、已经持有shared_lock再申请第二个shared_lock),对于非递归的std::shared_mutex来说也都是未定义行为,不要在生产代码中写这类逻辑。

内容的提问来源于stack exchange,提问作者kaba

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 10:48:11