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

C++多线程--条件变量

条件变量可以让多线程中一个线程优先进行,其他线程处于休眠状态,当条件变量通知notify_one()其他线程开始运行时,其他处于wait()状态的线程才会醒来
然后上锁,开始执行当前线程
在wait()状态下的其他线程会先解除当前的锁,之后再进入休眠,不占用CPU,之后notify后会先判断当前的锁是否解开并且是否满足当前要求然后才会唤醒子线程
值得一提的是条件变量中使用的锁一般是unique_lock(),这个锁可以自动解锁,也可以手动解锁,这样就保证了防止像gaurd_lock一样不解锁,同时可以通过move交换使用权
wait()中一般是传入一个mutex锁和一个lambda表达式返回为bool类型

点击查看代码
condition_variable cv;//条件变量
mutex mtx;//互斥锁
bool is_ready = false;//条件变量的条件
void fun(int &a)
{unique_lock<mutex> lock(mtx);//加锁cout << "thread fun is running..." << endl;a = 1100;is_ready = true;cv.notify_one();//通知等待条件变量的线程
}
void fun2(int& a)
{unique_lock<mutex> lock(mtx);//加锁cv.wait(lock, [] {return is_ready; });//等待条件变量满足cout << "thread fun2 is running..." << endl;a = 300;
}
int main()
{int a = 10;thread t1(fun, ref(a));thread t2(fun2, ref(a));t1.join();//等等t1子线程执行完t2.join();//等等t2子线程执行完cout << "now a==" << a << endl;cout << "Hello World!" << endl;return 0;
}
而条件变量应用的场景有,生产者消费者模型,线程池,下面是生产者消费者模型

其中在生产者消费者模型中,生产完一个元素后一定要记得解锁,不然消费者没有办法拿到对应的解锁状态,没有办法被唤醒

点击查看代码
condition_variable cv;//条件变量
mutex mtx;//互斥锁
queue<int>producer_queue;
void producer()
{for (int i = 0; i < 5; i++){{unique_lock<mutex>lock(mtx);producer_queue.push(i);cout << "生产了一个元素:" << i << endl;}cv.notify_one();this_thread::sleep_for(chrono::milliseconds(100)); // 模拟生产耗时}
}
void consumer()
{while (1){unique_lock<mutex>lock(mtx);cv.wait(lock, [] {return !producer_queue.empty(); });int temp = producer_queue.front();producer_queue.pop();cout << "弹出了一个元素:" << temp << endl;if (temp == 4)break;}
}
int main()
{thread producer_thread(producer);thread consumer_thread(consumer);producer_thread.join();consumer_thread.join();return 0;
}
条件变量使用时可能会出现的坑 丢失唤醒:如果wait()在notify()之后,那可能会导致子线程一直wait(),无法执行,要保证消费者先wait(),之后生产者才notify(),保证消费者比生产者快 下面代码会因为主线程的速度快于子线程,所以会先notify(),导致子线程一直wait()
点击查看代码
#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<atomic>
#include<queue>
using namespace std;
condition_variable cv;//条件变量
mutex mtx;//互斥锁
void fun()
{unique_lock<mutex> lock(mtx);cv.wait(lock);//等待条件变量的通知cout << "Thread is running..." << endl;
}
int main()
{thread t(fun);cv.notify_one();//通知一个等待线程t.join();return 0;
}
如果要修改的话需要让主线程加一个锁和判断条件,缓一下,让子线程先wait()
点击查看代码
#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<atomic>
#include<queue>
using namespace std;
condition_variable cv;//条件变量
mutex mtx;//互斥锁
bool ready = false;//条件变量的标志
void fun()
{unique_lock<mutex> lock(mtx);cv.wait(lock, [] {return ready; });//等待条件变量的通知cout << "Thread is running..." << endl;
}
int main()
{thread t(fun);cv.notify_one();//通知一个等待线程{unique_lock<mutex> lock(mtx);ready = true;//设置条件变量的标志}t.join();return 0;
}
http://www.jsqmd.com/news/982229/

相关文章:

  • 小程序制作需要花多少钱
  • 深入解析MC68HC08AZ32 GPIO:数据方向寄存器原理与实战配置
  • 避开这些坑!Cisco Packet Tracer实验常见错误排查与解决指南(附命令详解)
  • 不止是管理面板:深度挖掘Portainer在中小团队DevOps中的5个实战应用场景
  • 3分钟完成桌面美化:蔚蓝档案鼠标指针主题完整指南
  • Data Agent 热了两三年,为什么少见真正的标杆案例?
  • 终极1Fichier下载管理器:告别等待,体验极速文件下载
  • K32L3A引脚功能设计:从电气特性到系统集成的嵌入式硬件实战
  • QFN
  • 手把手调试 RuoYi-Vue-Plus 数据权限:用IDEA断点摸清 PlusDataPermissionInterceptor 的完整工作流
  • 为什么选择Sunshine:打造高性能个人游戏串流服务器的完整指南
  • LLM数据注入攻击全景解析:从训练投毒到RAG劫持的四层攻防实战
  • MC68HC908AT32 SPI与TIMA-4定时器寄存器配置与实战应用详解
  • 2026年6月蜂窝板吊顶厂家推荐:铝扣板/集成吊顶/客厅吊顶,家装与工程实力品牌深度解析! - 品牌推荐用户报道者
  • 门窗装修避坑指南:从选购到安装,一站式杜绝翻车(长沙南山世博特版) - 涂伟
  • 商家小程序怎么开通
  • 嵌入式硬件设计:从数据手册电气规格到可靠电路实战
  • 从数据手册到设计实战:KL15微控制器电气特性深度解读与低功耗优化指南
  • 探寻宜春高纯石英粉源头厂家的神秘面纱 - GrowthUME
  • Kodi IPTV Simple Client:打造家庭直播电视的终极指南
  • 春节倒计时归零后自动放烟花并跳转页面
  • 2026南昌冰淇淋蓝莓寿司门店排行:鲜度与创意实测 - 奔跑123
  • 商家小程序怎么做
  • 微信聊天记录永久保存终极指南:用留痕工具完整备份你的数字记忆
  • 量子传感新突破:GQSPI框架解决非对称信号检测难题
  • 保姆级教程:用MMSegmentation+UperNet+Swin-T搞定停车场场景语义分割(附完整代码与数据集)
  • 华三AC对接绿洲平台无线认证:从零到一的保姆级配置避坑指南
  • 如何通过Mac QuickLook插件实现文件预览效率翻倍:完整操作指南
  • PPPwn终极指南:3分钟掌握PS4内核漏洞利用技巧
  • 山东干粉砂浆设备厂家实测排行:5家合规供应商盘点 - 奔跑123