c++ - std::lock_guard 和 std::adopt_lock 行为而不锁定互斥锁
问题描述
我一直在学习,std::lock
并且std::lock_guard
大多数示例都遵循以下模式:
std::lock(m1, m2);
std::lock_guard<std::mutex> guard1(m1, std::adopt_lock);
std::lock_guard<std::mutex> guard2(m2, std::adopt_lock);
//Do something here
然后我遇到了一个示例,该示例使用了您在使用时会使用的相同模式std::unique_lock
,但使用的是lock_guard
:
std::lock_guard<std::mutex> guard1(m1, std::adopt_lock);
std::lock_guard<std::mutex> guard2(m2, std::adopt_lock);
std::lock(m1, m2);
//Do something here
我的问题是,如果您使用第二种模式并且在您到达之前发生异常,这会导致未定义的行为std::lock
吗?
PS 我知道引入了 C++17 std::scoped_lock
,std::lock_guard
它仍然存在,主要是为了与旧代码兼容。
解决方案
你的第二个例子是未定义的行为;adopt_lock
构造函数假定已持有互斥锁。此 UB 在构造时触发,而不是在销毁时或引发异常时触发。
如果您使用unique_lock
而不是scoped_lock
,则它具有:
unique_lock( mutex_type& m, std::defer_lock_t t ) noexcept;
构造函数,它允许您std::lock
稍作改动使用:
std::unique_lock<std::mutex> guard1(m1, std::defer_lock);
std::unique_lock<std::mutex> guard2(m2, std::defer_lock);
std::lock(guard1, guard2);
现在,unique_lock
确实跟踪它是否有锁,因此可能存在内存和性能开销;如果unique_lock
s 在范围内是本地的,编译器可以并且将优化它,如果它可以证明它是安全的。
如果编译器不能证明它是安全的,那么它通常是不安全的。
推荐阅读
- python - 最大的森林(亚马逊面试题)
- regex - 分隔符之间的正则表达式单个字符
- python - Python验证用户输入的数据问题
- angular - 在多组件角度使用组件延迟加载?
- apache-kafka - Kafka 代理在从生产者处获取消息时是否对页面缓存/磁盘进行零拷贝写入?如果是这样,它如何进行任何健全性检查?
- styled-components - 使用 Styled-Components,为什么我不能从条件中访问主题?
- javascript - 有没有办法从 Vue.js Mixin 调用递归函数?
- javascript - PageSpeed Insights:资源被延迟时显示“阻塞”
- wso2is - WSO2 无法访问外面
- firebase - Firebase 测试实验室读取特定国家/地区的短信