何时在std::shared_lock中使用defer_lock参数?
带std::defer_lock_t参数的std::shared_lock构造函数,核心作用是仅将锁对象与互斥量关联,但不立即获取锁,把锁的获取时机交给开发者手动控制,以此满足更灵活的同步需求。
核心作用
- 拆分"关联互斥量"与"获取锁"两个动作:让你可以先把锁和目标互斥量绑定,之后根据业务逻辑决定什么时候加锁。
- 适配复杂锁操作:配合
lock()、try_lock()、lock_for()等成员函数,实现阻塞加锁、尝试加锁、超时加锁等多样化的同步逻辑。
适用场景
1. 配合条件变量使用
当用shared_lock搭配条件变量时,通常需要在等待前解锁,被唤醒后重新加锁。用defer_lock构造锁对象,能先关联互斥量,再手动加锁,之后由条件变量自动处理解锁/重锁流程:
std::shared_mutex mtx; std::condition_variable_any cv; bool data_ready = false; void process_data() { std::shared_lock<std::shared_mutex> lock(mtx, std::defer_lock); lock.lock(); // 手动获取共享锁 // wait会自动解锁,直到条件满足后重新加锁 cv.wait(lock, []{ return data_ready; }); // 处理已准备好的数据 }
2. 多锁顺序控制(避免死锁)
当需要同时获取多个共享锁时,直接在构造时加锁可能因为加锁顺序不一致导致死锁。用defer_lock先关联所有锁,再通过std::lock()一次性加锁,能保证安全的加锁顺序:
std::shared_mutex mtx_a, mtx_b; void cross_resource_operation() { std::shared_lock<std::shared_mutex> lock_a(mtx_a, std::defer_lock); std::shared_lock<std::shared_mutex> lock_b(mtx_b, std::defer_lock); std::lock(lock_a, lock_b); // 原子性地同时获取两个锁,避免死锁 // 操作mtx_a和mtx_b保护的资源 }
3. 尝试非阻塞获取锁
如果希望尝试获取锁但不阻塞等待,用defer_lock构造后调用try_lock(),可以在获取失败时立即执行备用逻辑,而不会卡在构造阶段:
std::shared_mutex mtx; void try_process() { std::shared_lock<std::shared_mutex> lock(mtx, std::defer_lock); if (lock.try_lock()) { // 成功获取共享锁,处理资源 } else { // 获取失败,执行降级逻辑(比如返回提示、跳过操作) } }
简单来说,这个构造函数的存在,就是为了让开发者摆脱"构造即加锁"的固定流程,针对不同的同步场景,灵活控制锁的生命周期和获取时机。
内容的提问来源于stack exchange,提问作者gongliming7
相关产品推荐
相关产品推荐

