【C++并发编程】(四)条件变量

news2024/5/18 11:53:42

文章目录

  • (四)条件变量

(四)条件变量

条件变量(Condition Variable)用于线程间的同步,允许一个或多个线程在特定条件不满足时等待,并在条件满足时被其他线程唤醒。C++标准库中提供了的条件变量类std::condition_variable,其常用函数有:

  • std::condition_variable():默认构造函数

  • void notify_one(): 唤醒在该条件变量上等待的一个线程(如果有的话)。如果没有线程在等待,那么这个调用就没有效果。

  • void notify_all(): 唤醒在该条件变量上等待的所有线程。

  • void wait(std::unique_lock<std::mutex>& lock): 等待直到另一个线程调用该条件变量的 notify_one()notify_all()

以下例子展示std::condition_variable的使用:

例子1:使用notify_all唤醒所有线程

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;             // 全局互斥量
std::condition_variable cv; // 全局条件变量
bool ready = false;         // 共享条件

void worker_thread() {
    std::unique_lock<std::mutex> lck(mtx);
    while (!ready) { // 如果条件不满足,则等待
        cv.wait(lck); // 释放锁并等待,直到被唤醒
    }
    // 当条件满足时,每个线程都执行一些工作(这里只是打印)
    std::cout << "Thread " << std::this_thread::get_id() << " is working\n";
}

void go_all() {
    std::unique_lock<std::mutex> lck(mtx);
    ready = true; // 设置条件为true
    cv.notify_all(); // 唤醒所有等待的线程
}

int main() {
    std::thread threads[5]; // 创建5个线程
    for (int i = 0; i < 5; ++i) {
        threads[i] = std::thread(worker_thread);
    }

    std::cout << "5 threads ready to work...\n";

    go_all(); // 唤醒所有线程

    for (auto& th : threads) {
        th.join();
    }

    return 0;
}

在这个例子中,我们创建了5个线程,每个线程都试图打印其ID。但是,这些线程首先会检查一个共享条件ready。如果readyfalse,线程会调用cv.wait(lck)进入等待状态,并释放它持有的互斥量mtx

go_all函数中的ready被设置为true,并且调用了cv.notify_all()时,所有等待的线程都会被唤醒,并重新尝试获取互斥锁以继续执行。

注意:std::lock_guard 不提供等待条件变量的机制。因此,在需要使用条件变量(std::condition_variable)的上下文中,需要使用 std::unique_lock

例子2:使用notify_one唤醒一个线程

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;
int task = 0; // 模拟任务,只有一个线程可以处理

void worker_thread() {
    std::unique_lock<std::mutex> lck(mtx);
    while (!ready) {
        cv.wait(lck); // 等待条件成立
    }
    // 执行任务(这里只是打印)
    std::cout << "Thread " << std::this_thread::get_id() << " is processing task " << task << std::endl;
    // 任务完成,重置条件
    ready = false;
    task++; // 下一个任务
}

void go() {
    std::unique_lock<std::mutex> lck(mtx);
    ready = true; // 设置条件为true
    cv.notify_one(); // 唤醒一个等待的线程
}

int main() {
    std::thread threads[5]; // 创建5个线程
    for (int i = 0; i < 5; ++i) {
        threads[i] = std::thread(worker_thread);
    }

    std::cout << "5 threads ready to work...\n";

    // 假设有3个任务需要处理
    for (int i = 0; i < 3; ++i) {
        go(); // 唤醒一个线程处理任务
        std::this_thread::sleep_for(std::chrono::seconds(1)); // 假设处理任务需要一些时间
    }

    for (auto& th : threads) {
        th.join();
    }

    return 0;
}

在这个例子中,每次调用go()函数时,都会唤醒一个等待的线程来处理任务。由于我们调用了go()三次,所以只会有三个线程被唤醒并处理任务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1641748.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

D3CTF2024

文章目录 前言notewrite_flag_where【复现】D3BabyEscapePwnShell 前言 本次比赛笔者就做出两道简单题&#xff0c;但队里师傅太快了&#xff0c;所以也没我啥事。然后 WebPwn 那题命令行通了&#xff0c;但是浏览器不会调试&#xff0c;然后就简单记录一下。 note 只开了 N…

【热门话题】如何构建具有高度扩展性的系统

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 如何构建具有高度扩展性的系统引言一、理解扩展性1.1 扩展性的定义1.2 扩展性的…

3GPP官网下载协议步骤

1.打开官网 https://www.3gpp.org/ 2.点击 3.在界面选择要找的series&#xff0c;跳转到查找界面 以V2X通信协议为例&#xff0c;论文中通常会看到许多应用&#xff1a; [7] “Study on evaluation methodology of new Vehicle-to-Everything (V2X) use cases for LTE and NR…

2-手工sql注入(进阶篇) sqlilabs靶场1-4题

1. 阅读&#xff0c;学习本章前&#xff0c;可以先去看看基础篇&#xff1a;1-手工sql注入(基础篇)-CSDN博客 2. 本章通过对sqlilabs靶场的实战&#xff0c;关于sqlilabs靶场的搭建&#xff1a;Linux搭建靶场-CSDN博客 3. 本章会使用到sqlmap&#xff0c;关于sqlmap的命令&…

C 深入指针(2)

目录 1 野指针 1.1 成因 1.2 如何规避野指针 2 assert 断言 2.1 用法 2.2 assert 的优点 2.1 assert 的缺点 3 小注解 3.1 Debug 和 Release 1 野指针 【概念】&#xff1a; 野指针就是指针指向的位置是不可知的&#xff08;随机的、不正确的、没有明确限制的&#…

解决windows下无法安装Hyper-V

在windows中打开hyper-v的办法如下&#xff1a;&#xff08;但不适用无法安装hyper-v的windows系统如win10家庭版&#xff09; 通过「控制面板」是启用 Hyper-V 最直接的方法&#xff1a; 1 使用Windows R快捷键打开「运行」对话框&#xff0c;执行appwiz.cpl以打开「控制面…

关于win平台c语言引入开源库的问题与解决

许久不写博客&#xff0c;五一还在加班&#xff0c;就浅浅写一篇吧 最近除了做物联网平台 还对网关二次开发程序做了修改&#xff0c;网关的二次开发去年年底的时候做过&#xff0c;但是当时的逻辑不是十分完善&#xff0c;差不多已经过了半年了&#xff0c;很多细节已经忘记了…

Java--方法的使用

1.1什么是方法 方法顾名思义就是解决问题的办法&#xff0c;在程序员写代码的时候&#xff0c;会遇到很多逻辑结构一样&#xff0c;解决相同问题时&#xff0c;每次都写一样的代码&#xff0c;这会使代码看起来比较绒余&#xff0c;代码量也比较多&#xff0c;为了解决这个问题…

VBA 根据表格指定列拆分多sheet

一. 需求 ⏹ 根据部分列&#xff0c;拆分数据到多个sheet页 二. 代码 ⏹ 重点代码摘要 CreateObject("scripting.dictionary")&#xff1a;创建一个字典对象&#xff0c;相当于Java中的MapDim aRef() As String&#xff1a;定义一个存储字符串类型的数组ReDim aRe…

Linux学习之IP协议

前言&#xff1a; 在学习IP协议i前&#xff0c;我们其实知道网络协议栈是一层层的&#xff0c;上层封装好之后就传给下层&#xff0c;对于我们治安学习到的TCP协议&#xff0c;在对数据进行封装之后&#xff0c;并不是直接就将数据进行传输&#xff0c;而是交给下一层网络层进…

【讲解如何OpenCV入门】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

GDPU unity游戏开发 碰撞器与触发器

砰砰叫&#xff0c;谁动了她的奶酪让你的小鹿乱撞了。基于此&#xff0c;亦即碰撞与触发的过程。 碰撞器与触发器的区别 通俗点讲&#xff0c;碰撞器检测碰撞&#xff0c;触发器检测触发&#xff0c;讲了跟没讲似的。碰撞器是用来检测碰撞事件的&#xff0c;在unity中&#xff…

发表博客之:transformer 架构 推理时候运算流程详细讲解,小白都可以看得懂,AI推理工程师必备技能!

文章目录 [发表博客之&#xff1a;transformer 架构 推理时候 详细讲解&#xff0c;小白都可以看得懂&#xff0c;AI推理工程师必备技能&#xff01;](https://cyj666.blog.csdn.net/article/details/138439826)总结一下 发表博客之&#xff1a;transformer 架构 推理时候 详细…

[每日AI·0501]GitHub 版 Devin,Transformer的强力挑战者 Mamba,Sora 制作细节与踩坑,OpenAI 记忆功能

AI 资讯 国资委&#xff1a;加快人工智能等新技术与制造全过程、全要素深度融合GitHub版 Devin 上线&#xff0c;会打字就能开发应用&#xff0c;微软 CEO&#xff1a;重新定义 IDE在12个视频理解任务中&#xff0c;Mamba 先打败了 TransformerSora 会颠覆电影制作吗&#xff…

Python | Leetcode Python题解之第66题加一

题目&#xff1a; 题解&#xff1a; class Solution:def plusOne(self, digits: List[int]) -> List[int]:n len(digits)for i in range(n - 1, -1, -1):if digits[i] ! 9:digits[i] 1for j in range(i 1, n):digits[j] 0return digits# digits 中所有的元素均为 9retu…

Java——认识异常

目录 一.异常的概念与体系结构 1.异常的概念 1.1算术异常 1.2数组越界异常 1.3空指针异常 2.异常的体系结构 3.异常的分类 3.1编译时异常 3.2运行时异常 二.异常的处理 1.防御式编程 1.1LBYL 1.2EAFP&#xff08;核心&#xff09; 2.异常的抛出 3.异常的捕获 3…

1081 检查密码(测试点2简析)

solution 潜在的非法字符里可能包含空格&#xff0c;所以不能直接用cin接收string&#xff08;测试点2&#xff09; #include<iostream> #include<string> using namespace std; int judge(string s){if(s.size() < 6) return 1;int num 0, c 0;for(int i …

C++基础——输入输出(文件)

一、标准输入输出流 C 的输入输出是程序与用户或外部设备&#xff08;如文件、网络等&#xff09;之间交换信息的过程。 C 提供了丰富的标准库来支持这种交互&#xff0c;主要通过流的概念来实现。 流&#xff1a;抽象概念&#xff0c;表示一连串的数据&#xff08;字节或字…

Python爬虫--爬取糗事百科段子

爬取糗事百科段子&#xff1a; 段子在 <div class"content"> 里面的 <span> 标签里面 不过这里有个坑&#xff0c;div 标签跟 span 标签 之间有很多空行 普通 .*? 是匹配不了的&#xff0c;需要使用模式修饰符 S S 的意思 让 .(点) 匹配&#xff0c…

政安晨:【Keras机器学习示例演绎】(三十一)—— 梯度集中,提高训练效果

目录 简介 设置 准备数据 使用数据增强 定义模型 实现梯度集中化 训练工具 不使用 GC 训练模型 使用 GC 训练模型 性能比较 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras机器学习实战 希望政安晨的博客能够对…