C++并发编程实战:深入理解条件变量(std::condition_variable)
【免费下载链接】Cpp_Concurrency_In_Action 项目地址: https://gitcode.com/gh_mirrors/cp/Cpp_Concurrency_In_Action
条件变量概述
条件变量是多线程编程中重要的同步机制,它允许线程在某些条件不满足时主动阻塞,直到其他线程通知条件可能已经改变。在C++标准库中,<condition_variable>头文件提供了两种条件变量实现:std::condition_variable和std::condition_variable_any。
std::condition_variable详解
基本特性
std::condition_variable是C++标准库提供的高效条件变量实现,它必须与std::unique_lock<std::mutex>配合使用。这种设计优化了性能,但限制了使用场景。
class condition_variable {
public:
condition_variable();
~condition_variable();
// 通知一个等待线程
void notify_one() noexcept;
// 通知所有等待线程
void notify_all() noexcept;
// 等待函数
void wait(std::unique_lock<std::mutex>& lock);
template <typename Predicate>
void wait(std::unique_lock<std::mutex>& lock, Predicate pred);
// 带超时的等待函数
template <typename Clock, typename Duration>
cv_status wait_until(std::unique_lock<std::mutex>& lock,
const std::chrono::time_point<Clock, Duration>& absolute_time);
// 其他等待函数...
};
核心功能解析
-
等待机制:
wait()会使当前线程阻塞,直到被通知或发生伪唤醒- 伪唤醒是指线程在没有收到通知的情况下被唤醒,因此通常需要在循环中检查条件
-
通知机制:
notify_one()唤醒一个等待线程notify_all()唤醒所有等待线程
-
谓词等待:
- 带谓词的
wait()版本会自动处理伪唤醒问题 - 相当于
while(!pred()) wait(lock);
- 带谓词的
实际应用示例
std::mutex mtx;
std::condition_variable cv;
bool data_ready = false;
// 生产者线程
void producer() {
std::unique_lock<std::mutex> lock(mtx);
// 生产数据...
data_ready = true;
cv.notify_one();
}
// 消费者线程
void consumer() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, []{ return data_ready; });
// 消费数据...
}
std::condition_variable_any详解
与std::condition_variable的区别
std::condition_variable_any提供了更通用的接口,可以与任何满足基本锁概念(Lockable)的类型一起使用,而不仅限于std::unique_lock<std::mutex>。
class condition_variable_any {
public:
// 类似condition_variable的接口,但模板化Lockable类型
template<typename Lockable>
void wait(Lockable& lock);
template <typename Lockable, typename Predicate>
void wait(Lockable& lock, Predicate pred);
// 其他成员函数...
};
适用场景
- 需要与其他锁类型(如共享锁)配合使用时
- 需要更灵活的锁管理策略时
- 需要与第三方锁实现配合使用时
条件变量使用的最佳实践
- 总是使用谓词检查:避免伪唤醒问题
- 合理选择通知方式:
notify_one()性能更好notify_all()确保不会遗漏任何等待线程
- 注意锁的生命周期:确保在等待期间持有正确的锁
- 避免虚假唤醒:即使使用谓词版本,也要确保谓词检查是线程安全的
- 考虑性能影响:条件变量的唤醒操作可能引起上下文切换,影响性能
高级主题:线程退出通知
std::notify_all_at_thread_exit函数允许在线程退出时自动通知条件变量:
void worker(std::condition_variable& cv, std::mutex& mtx) {
std::unique_lock<std::mutex> lock(mtx);
// ...做一些工作...
std::notify_all_at_thread_exit(cv, std::move(lock));
// 函数返回时自动调用cv.notify_all()
}
这个机制对于实现线程池等场景非常有用,可以确保线程完成工作后正确地通知其他等待线程。
总结
条件变量是C++多线程编程中强大的同步原语,正确使用它们可以构建高效、可靠的并发系统。理解std::condition_variable和std::condition_variable_any的区别及适用场景,掌握等待/通知机制的正确用法,是成为熟练的C++并发程序员的关键一步。
【免费下载链接】Cpp_Concurrency_In_Action 项目地址: https://gitcode.com/gh_mirrors/cp/Cpp_Concurrency_In_Action
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



