当前位置: 首页 > ai >正文

C++ 条件变量与线程通知机制:std::condition_variable

✅ 简介

  • std::condition_variable 是 C++11 引入的线程间通信机制,允许线程在某个条件满足时被唤醒。
  • 通常与 std::mutex 一起配合使用,用于实现生产者-消费者模型、线程等待任务等场景。

🔄 基本原理

  • 一个线程调用 wait() 进入阻塞状态,直到另一个线程调用 notify_one()notify_all()
  • wait() 会自动释放传入的 mutex,并在被唤醒时重新获取锁。

⚠️ 虚假唤醒(Spurious Wakeup)

  • 调用 wait() 的线程有可能在没有收到通知时被唤醒,这被称为虚假唤醒
  • 因此,推荐使用带谓词版本的 wait(lock, predicate) 形式:
    cv.wait(lock, []{ return 条件满足; });
    
  • 这样即使发生虚假唤醒,wait 也会再次检查条件是否成立,确保线程只有在需要时才继续执行。

🔧 使用方式

示例:生产者-消费者模型(含虚假唤醒处理)

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <atomic>
#include <csignal>
#include <chrono>std::mutex mtx;
std::condition_variable cv;
std::queue<int> dataQueue;
std::atomic<bool> stop{false};// 信号处理函数,捕获 Ctrl+C
void signalHandler(int signum) {stop = true;cv.notify_all(); // 通知所有等待的线程
}void producer() {int i = 0;while (!stop) {{std::unique_lock<std::mutex> lock(mtx);dataQueue.push(i);std::cout << "Produced: " << i << std::endl;++i;}cv.notify_one(); // 通知一个等待的线程std::this_thread::sleep_for(std::chrono::seconds(1)); // 休眠 1 秒}cv.notify_all(); // 通知消费者停止
}void consumer() {while (true) {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [] { return !dataQueue.empty() || stop; }); // 等待数据或停止信号if (!dataQueue.empty()) {std::cout << "Consumed: " << dataQueue.front() << std::endl;dataQueue.pop();lock.unlock(); // 提前解锁以减少锁持有时间std::this_thread::sleep_for(std::chrono::seconds(1)); // 休眠 1 秒} else if (stop) {break; // 队列为空且收到停止信号,退出}}
}int main() {// 注册信号处理函数std::signal(SIGINT, signalHandler);std::thread t1(producer);std::thread t2(consumer);t1.join();t2.join();return 0;
}

☑️ 关键函数说明

函数名说明
wait(lock)等待并释放锁,直到 notify_one 被调用。⚠️ 可能发生虚假唤醒。
wait(lock, predicate)带条件的等待,直到 predicate 返回 true。✅ 推荐用法
notify_one()唤醒一个等待的线程。
notify_all()唤醒所有等待的线程。

📌 总结

特性描述
同步机制用于线程之间的通信
等待效率阻塞等待,不占用 CPU
虚假唤醒可能无通知就被唤醒,需使用谓词保护
适用场景生产者-消费者、线程池任务调度等
配套使用std::mutex + std::unique_lock 配合
http://www.xdnf.cn/news/6597.html

相关文章:

  • PD 分离推理的加速大招,百度智能云网络基础设施和通信组件的优化实践
  • 【data】上海膜拜数据
  • AWS云入门宝典
  • STM32外设AD/DA-基础及CubeMX配置
  • Web性能优化的未来:边缘计算、AI与新型渲染架构
  • 排序01:多目标模型
  • SQL Server权限设置的几种方法
  • 每周靶点:CA125、AFP分享
  • Hue面试内容整理-示例编码题
  • 如何选择高性价比的 1T 服务器租用服务​
  • 【Android构建系统】了解Soong构建系统
  • JS手写代码篇---手写 instanceof 方法
  • AGI大模型(18):各大平台RAG实现之智普RAG
  • 达梦数据库多版本并发控制(MVCC)_yxy
  • 5G 技术在智能制造中的应用:加速工业革命的新引擎
  • OpenCV 背景建模详解:从原理到实战
  • BeeWare创建APK应用初体验
  • 仿生机械轮腿式车辆在丘陵和山区姿态控制的方法
  • 用整数划分整理结构
  • Linux系统篇——文件描述符FD
  • TC8:SOMEIP_ETS_029-030
  • Stainer Chain的镜像对称性的充分必要条件
  • Unity 拖尾烟尘效果及参数展示
  • qt文本边框设置
  • 解决“VMware另一个程序已锁定文件的一部分,进程无法访问“
  • 机器学习与人工智能:NLP分词与文本相似度分析
  • 反射机制详细说明
  • 2025/5/16
  • 费曼技巧及提高计划
  • Font导致内存泄漏问题排查记录