C++中搭配adopt_lock_t的lock具体含义及使用疑问
adopt_lock_t文档中assume的语义及错误使用后果 「assume」的具体含义
这里的assume是标准库和调用方之间的前置条件约定,不附带任何运行时检查逻辑:标准库实现会直接认定调用方已经满足「构造锁对象的当前线程,已经持有了传入互斥量的所有权」这个前提,构造过程中不会执行任何加锁操作,仅完成锁对象和互斥量的绑定,等锁对象生命周期结束析构时,自动执行互斥量的解锁操作。
简单说就是,这个标签相当于调用方向标准库做出“锁我已经拿到了,你只管帮我到点释放就行”的保证,标准库不会做任何校验,完全信任该保证,不满足前提的所有后果由调用方自行承担。
互斥量被其他线程持有时传入adopt_lock_t的后果
这种用法完全违反前置条件,属于标准明确规定的未定义行为,没有任何可预期的确定结果,实际开发中常见的表现有:
- 锁对象析构时,当前线程根本不持有对应互斥量,解锁操作直接触发操作系统线程库错误,比如pthread环境下返回
EPERM错误,直接导致进程终止 - 互斥量内部的状态、持有计数被破坏,后续所有针对该互斥量的加锁、解锁逻辑错乱,引发死锁、多线程数据竞争、随机内存损坏等极难复现排查的问题
- 若使用带调试校验的标准库版本(如GCC libstdc++ debug模式、MSVC debug运行时),会第一时间触发断言崩溃,在开发阶段直接暴露问题
正确使用示例
adopt_lock_t仅适用于已经手动获取锁所有权,需要把解锁责任交给RAII锁对象托管的场景:
std::mutex mtx; // 手动获取互斥量所有权 mtx.lock(); // 传入adopt_lock标签,让lock_guard接管锁的释放责任,出作用域自动解锁 std::lock_guard<std::mutex> guard(mtx, std::adopt_lock); // 后续不需要手动调用mtx.unlock()
注意:永远不要在当前线程未持有目标互斥量的情况下,使用
adopt_lock_t构造锁对象。
内容的提问来源于stack exchange,提问作者f1msch
相关产品推荐
相关产品推荐

