当前位置: 首页 > 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.rkmt.cn/news/1493964.html

相关文章:

  • 手把手调试 RuoYi-Vue-Plus 数据权限:用IDEA断点摸清 PlusDataPermissionInterceptor 的完整工作流
  • 从数据手册到设计实战:KL15微控制器电气特性深度解读与低功耗优化指南
  • 门窗装修避坑指南:从选购到安装,一站式杜绝翻车(长沙南山世博特版) - 涂伟
  • 2026年6月蜂窝板吊顶厂家推荐:铝扣板/集成吊顶/客厅吊顶,家装与工程实力品牌深度解析! - 品牌推荐用户报道者
  • LLM数据注入攻击全景解析:从训练投毒到RAG劫持的四层攻防实战
  • MC68HC908AT32 SPI与TIMA-4定时器寄存器配置与实战应用详解
  • 探寻宜春高纯石英粉源头厂家的神秘面纱 - GrowthUME
  • 2026南昌冰淇淋蓝莓寿司门店排行:鲜度与创意实测 - 奔跑123
  • 商家小程序怎么做
  • 保姆级教程:用MMSegmentation+UperNet+Swin-T搞定停车场场景语义分割(附完整代码与数据集)
  • 量子传感新突破:GQSPI框架解决非对称信号检测难题
  • 30K+ AI产品经理进阶指南:4个月从0到实战,掌握大模型调优核心技能!2026年AI产品经理学习路线
  • Visio 2021从入门到放弃?不!这5个隐藏功能让你画图效率翻倍(附实战案例)
  • MuleSoft+LLM企业级AI集成:构建可信可审计的AI工作流
  • 5步掌握Beyond Compare 5激活:从密钥生成到永久使用
  • 北京不锈钢橱柜定制厂家排行:工艺与服务核心维度实测 - 奔跑123
  • 如何为Calibre添加智能元数据抓取:3步实现自动化书籍管理终极指南
  • 嵌入式Linux NFS启动配置实战:基于MPC8220与MontaVista 3.1
  • 武汉装修为什么总超支?12年老牌装企揭开增项真相 - 资讯纵览
  • 想挑选高性价比电缆故障测试仪厂家 这些实用选购技巧建议提前了解 - GrowthUME
  • WVP-GB28181-Pro终极指南:如何快速构建企业级视频监控平台
  • 从IBM 750CX到MPC7447A:PowerPC架构迁移实战与性能优化
  • 广义串并联平面图
  • Xenia Canary:如何在现代PC上完美运行Xbox 360游戏的完整指南
  • 5分钟学会Illustrator批量替换神器:告别重复劳动的设计效率革命
  • 2026石家庄黄金回收实测:这家断层第一,实力高价真靠谱 - 奢侈品回收测评
  • 火狐浏览器搭配Video DownloadHelper插件,你的个人视频素材库搭建指南(2024实测版)
  • 欧盟标准107胶实测:3大性能对比与选购避坑指南 - 品牌优选官
  • Java写的传感器模拟采集+图表实时显示系统(带源码和运行说明)
  • 2026手机证件照换装保姆级教程,多款实用方法+APP/小程序推荐 - 办公小帮手