news 2026/9/4 1:23:17

多线程中的std::condition_variable条件变量学习

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
多线程中的std::condition_variable条件变量学习

std::condition_variable 是与 std::mutex 一起使用的同步原语,它能用于阻塞一个线程,或同时阻塞多个线程,直至另一线程修改共享变量(条件)并通知 std::condition_variable。
有意修改共享变量的线程必须
1.获得 std::mutex(常通过 std::lock_guard)
2.在保有锁时进行修改
3.在std::condition_variable上执行notify_one或notify_all(可以释放锁后再通知)
即使共享变量是原子的,也必须在拥有互斥体时修改它,以把修改发布到等待的线程。

下面来看具体的使用示例

//condition_variable.cpp condition_variable example //#include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex #include <condition_variable> #include <string> std::mutex mtx; std::condition_variable cv; std::string data; bool ready = false; bool processed = false; void worker_thread() { //等待直至 main() 发送数据 std::unique_lock lk(mtx); printf("worker_thread=1============ready=======%d\n", ready); cv.wait(lk, [] {return ready; }); printf("worker_thread=2============ready=======%d\n", ready); std::this_thread::sleep_for(std::chrono::seconds(2)); //暂停2秒 // 等待后,我们占有锁 printf("工作线程正在处理数据\n"); data += "(处理后)"; // 发送数据回 main() processed = true; printf("工作线程指示数据已经处理完成\n"); // 通知前完成手动解锁,以避免等待线程才被唤醒就阻塞(细节见 notify_one) lk.unlock(); cv.notify_one(); } int main() { //1.记录开始时间点 auto start = std::chrono::steady_clock::now(); std::thread worker(worker_thread); data = "数据样例"; // 发送数据到 worker 线程 { std::lock_guard lk(mtx); //std::this_thread::sleep_for(std::chrono::seconds(2)); //暂停2秒 ready = true; printf("main() 指示数据已准备好进行处理\n"); } cv.notify_one(); // 等候 worker { std::unique_lock lk(mtx); printf("main=1============processed=======%d\n", processed); cv.wait(lk, [] { return processed; }); printf("main=2============processed=======%d\n", processed); } printf("返回 main(),data = %s\n", data.c_str()); worker.join(); //2.记录结束时间点 auto end = std::chrono::steady_clock::now(); //3.计算时间差 auto elapsed = end - start; printf("耗时: %lld 纳秒\n", std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed).count()); printf("耗时: %lld 微秒\n", std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count()); printf("耗时: %lld 毫秒\n", std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count()); printf("耗时: %lld 秒\n", std::chrono::duration_cast<std::chrono::seconds>(elapsed).count()); printf("hello learn condition_variable\n"); return 0; }

编译运行:

下面来看wait()一个参数的示例

//condition_variable2.cpp condition_variable example //#include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex #include <condition_variable> std::mutex mtx; std::condition_variable cv; bool ready = false; void print_id(int id) { std::unique_lock<std::mutex> lck(mtx); printf("print_id=1============id=======%d\n", id); while (!ready) cv.wait(lck); printf("print_id=2============id=======%d\n", id); std::this_thread::sleep_for(std::chrono::seconds(1)); //暂停2秒 printf("thread========id=%d\n", id); } void go() { std::unique_lock<std::mutex> lck(mtx); printf("go=1====================\n"); //std::this_thread::sleep_for(std::chrono::seconds(12)); //暂停2秒 ready = true; cv.notify_all(); //通知所有线程 } int main() { //1.记录开始时间点 auto start = std::chrono::steady_clock::now(); std::thread threads[10]; // spawn 10 threads: for (int i = 0; i < 10; ++i) threads[i] = std::thread(print_id, i); printf("10 threads ready to race...\n"); go(); printf("main=1====================\n"); for (auto& th : threads) th.join(); printf("main=1====================\n"); //2.记录结束时间点 auto end = std::chrono::steady_clock::now(); //3.计算时间差 auto elapsed = end - start; printf("耗时: %lld 纳秒\n", std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed).count()); printf("耗时: %lld 微秒\n", std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count()); printf("耗时: %lld 毫秒\n", std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count()); printf("耗时: %lld 秒\n", std::chrono::duration_cast<std::chrono::seconds>(elapsed).count()); printf("hello learn condition_variable\n"); return 0; }

编译运行:

参考:

https://zh.cppreference.com/cpp/thread/condition_variable

https://cplusplus.com/reference/condition_variable/condition_variable/

https://blog.csdn.net/m0_67168421/article/details/128302838
https://blog.csdn.net/FL1768317420/article/details/136613939
https://blog.csdn.net/u011808673/article/details/91783965
https://liucjy.blog.csdn.net/article/details/130298493
https://lizuohao.blog.csdn.net/article/details/136274149

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/4 1:21:49

视频生成API接入全攻略:Seedance 2.5 实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/4 1:20:23

分数阶Lorenz系统Lyapunov指数Matlab实操指南

简介&#xff1a;本资源是一套面向计算机、电子信息工程及数学专业本科生的分数阶Lorenz系统Lyapunov指数数值计算Matlab实现方案&#xff0c;适用于课程设计、期末大作业与毕业设计等实践环节&#xff0c;帮助学习者掌握混沌系统定量分析的核心方法。压缩包共4个文件&#xff…

作者头像 李华
网站建设 2026/9/4 1:17:57

【04】程序员之歌

程序员之歌 朝阳承载你青春的气息&#xff0c;晚霞承载你忙碌的荣光&#xff0c;星夜灯光是你疲劳身躯坚持鏖战的抚慰。为什么这样忙&#xff1f;为什么这么累&#xff1f;因为项目里有无限的任务与责任。忍耐是你坚守的源泉&#xff0c;信念是你前进的动力&#xff0c;追逐梦想…

作者头像 李华
网站建设 2026/9/4 1:17:52

基于HD44780的字符型液晶显示模块接口的单片机实现

基于HD44780的LCD的实现 —4Bit 接口 前言 HD44780是点阵式的LCD控制器&#xff0c;它能显示英文字母、阿拉伯数字、日文片假名和一般性的符号。微处理器可以使用2种方式来驱动他4-bit或者8-bit。 下面是HD44780的组成图&#xff08;xiaobin&#xff09; 网上有许多基于8-bit的…

作者头像 李华