今天一次讲明白C++条件变量

news2024/9/20 9:43:52

在C++中,std::condition_variable 条件变量是一个同步原语,它允许一个或多个线程在某个条件成立时,被另一个线程唤醒。std::condition_variable 条件变量通常与互斥锁(std::mutex)一起使用,以保护共享数据和同步线程之间的通信。

条件变量的使用场景

条件变量主要用于以下场景:

  1. 等待/通知模型:一个或多个线程等待某个条件成立,另一个线程在条件成立时通知等待的线程。
  2. 生产者/消费者问题:生产者线程生产数据后通知消费者线程,消费者线程等待生产者生产数据。

条件变量的基本使用步骤

  1. 定义互斥锁和条件变量:首先,你需要定义一个互斥锁(例如std::mutex)和一个 std::condition_variable 条件变量。
  2. 锁定互斥锁:在调用 std::condition_variable 条件变量的 wait 或 wait_for 等函数之前,必须先锁定互斥锁。
  3. 调用条件变量的等待函数:调用 wait、wait_for 或 wait_until 等函数来等待条件成立。这些函数会释放互斥锁,使其他线程可以进入临界区,并在条件变量上等待。当其他线程调用 std::condition_variable 条件变量的 notify_one 或 notify_all 来唤醒等待的线程时,等待的线程会重新获取互斥锁并继续执行。
  4. 检查条件:在 wait、wait_for 或 wait_until 返回后,通常需要重新检查条件是否满足,因为可能存在虚假唤醒(spurious wakeup)的情况。
  5. 解锁互斥锁:在离开临界区时,需要解锁互斥锁。

使用示例

以下是一个简单的生产者/消费者问题的示例,展示了 std::condition_variable 条件变量的使用:

#include <iostream>  
#include <thread>  
#include <mutex>  
#include <condition_variable>  
#include <queue>  
  
std::mutex g_mtx;  
std::condition_variable g_cv;  
std::queue<int> g_queue;  
bool g_done = false;  
  
// 生产者函数
void producer(int id) {  
    for (int i = 0; i < 10; ++i) {  
        std::unique_lock<std::mutex> lck(g_mtx);  
        g_queue.push(id * 10 + i);  
        std::cout << "Produced: " << id * 10 + i << std::endl;  
        lck.unlock();  
        g_cv.notify_one(); // 通知一个等待的线程  
    }  
  
    {  
        std::lock_guard<std::mutex> lck(g_mtx);  
        g_done = true;  
    }  
    g_cv.notify_all(); // 通知所有等待的线程  
}  
  
// 消费者函数
void consumer() {  
    std::unique_lock<std::mutex> lck(g_mtx);
    while (!g_done && g_queue.empty()) {  
        g_cv.wait(lck); // 等待条件成立  
    }  
  
    while (!g_queue.empty()) {  
        int val = g_queue.front();  
        g_queue.pop();  
        std::cout << "Consumed: " << val << std::endl;  
        lck.unlock();  
  
        // 模拟耗时操作,等待100毫秒  
        std::this_thread::sleep_for(std::chrono::milliseconds(100));  
  
        lck.lock();  
    }  
}  
  
int main() {  
    std::thread producers[2];      // 生产者线程池
    std::thread consumers[5];      // 消费者线程池
  
    // 创建生产者  
    for (int i = 0; i < 2; ++i) {  
        producers[i] = std::thread(producer, i);  
    }  
  
    // 创建消费者  
    for (int i = 0; i < 5; ++i) {  
        consumers[i] = std::thread(consumer);  
    }  
  
    // 等待生产者完成  
    for (auto& t : producers) {  
        t.join();  
    }  
  
    // 唤醒所有等待的消费者(尽管这里可能不是必需的,因为done标志已经设置)  
    g_cv.notify_all();  
  
    // 等待消费者完成  
    for (auto& t : consumers) {  
        t.join();  
    }  
  
    return 0;  
}

在这个例子中,生产者和消费者线程使用条件变量(g_cv)和互斥锁(g_mtx)来同步对共享队列(g_queue)的访问。生产者生产数据后,通过调用notify_one来唤醒一个等待的消费者线程。当所有生产者都完成生产后,它们将done标志设置为true,并通过调用`notify_all 来唤醒所有的消费者线程。

-End-

#想了解更多精彩内容,关注下方公众号。

本人小杨哥:

超20年C++开发经验,独立软件开发;著名开源产品高并发C++应用服务器MYCP作者;开源企业即时通讯软件Entboost首席架构师;开发有【WordBN字远笔记】等共享软件产品。

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

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

相关文章

David Baker 任科学顾问,初创公司发布世界最大蛋白质相互作用数据库,已获 8 轮融资

蛋白质-蛋白质相互作用 (Protein-Protein Interactions, PPI) 是细胞生命活动的重要组成部分&#xff0c;在调控和维持细胞的生理功能中&#xff08;如细胞的信号传导、代谢反应和基因表达&#xff09;发挥着不可或缺的作用。 然而目前 PPl 数据库中的数据相对较少&#xff0c…

穿越病毒区-第15届蓝桥省赛Scratch中级组真题第2题

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第187讲。 如果想持续关注Scratch蓝桥真题解读&#xff0c;可以点击《Scratch蓝桥杯历年真题》并订阅合集&#xff0c;…

CCF201912_1

题解&#xff1a; #include<bits/stdc.h>using namespace std;int n;bool shouldSkip(int num) {if (num % 7 0){return true;}while (num > 0){if (num % 10 7){return true;}num / 10;}return false; } int main() {scanf("%d", &n);int b[4] { 0…

Android Studio 安装配置教程(Windows最详细版)

目录 前言 Android Studio 下载 Android Studio 安装 Android Studio 使用 一、创建默认项目&#xff08;Compose&#xff09; 二、创建常规项目 三、使用ViewBinding 四、查看Gradle版本、SDK版本、JDK版本 ① Gradle版本 ② SDK版本 ③ JDK版本 前言 Android开发…

跟《经济学人》学英文:2024年09月14日这期 The sweet story of Peru’s blueberry boom

The sweet story of Peru’s blueberry boom Plucky farmers have transformed the market in only ten years plucky&#xff1a;英 [ˈplʌki] 勇敢的&#xff1b;无畏的&#xff1b;有胆识的 原文&#xff1a; Peru’s blueberry harvest is just beginning, and Ivan Ja…

自动驾驶:LQR、ILQR和DDP原理、公式推导以及代码演示(七、CILQR约束条件下的ILQR求解)

&#xff08;七&#xff09;CILQR约束条件下的ILQR求解 CILQR&#xff08;(Constrained Iterative Linear Quadratic Regulator)&#xff09; 是为了在 iLQR 基础上扩展处理控制输入和状态约束的问题。在这种情况下&#xff0c;系统不仅要优化控制输入以最小化代价函数&#x…

NET WPF使用组件库HandyControl

一、背景 WPF原生控件提供的API功能不够强大&#xff0c;设置一般的功能都需要进行很复杂的配置和实现。 1.1 原生按钮控件 例如&#xff0c;原生控件<Button/> 默认效果是这样的&#xff1a; MainWindow.xaml代码&#xff1a; <Window x:Class"wpf_demo.Mai…

SAP_ABAP_编程基础

SAP ABAP 顾问能力模型(同心圆方法论)_sap abap 顾问能力模型(同心圆方法论)-CSDN博客文章浏览阅读1.8k次,点赞5次,收藏35次。目标:基于对SAP abap 顾问能力模型的梳理,给一年左右经验的abaper 快速成长为三年经验提供超级燃料!_sap abap 顾问能力模型(同心圆方法论)htt…

我们的Python服务器开发脚手架开放了

pdServer是我们实践过程中的产物&#xff0c;当我们在开发各类python应用时&#xff0c;经常需要一个server来提供服务。于是我们使用fastApi来提实现&#xff0c;并在这个过程中不断的完善&#xff0c;实现了JWT\SQL等。 我们的脚手架项目可以&#xff1a; fastApi实现一个服…

数据线电子行业MES系统功能与生产过程管理

万界星空科技针对数据线电子行业的MES系统&#xff08;制造执行系统&#xff09;&#xff0c;其具体功能、生产过程管理以及注塑机设备数据采集等方面&#xff0c;可以详细介绍如下&#xff1a; 一、电子行业MES系统具体功能 计划管理&#xff1a; MES系统能够根据客户需求和销…

潍坊网站建设-高端建站

在当今数字化时代&#xff0c;企业的在线形象越来越重要。潍坊作为一个经济发展迅速的城市&#xff0c;许多企业都意识到拥有一个高端网站的重要性。潍坊网站建设不仅仅是技术层面的开发&#xff0c;更是品牌形象和市场竞争力的体现。高端建站的核心在于用户体验、视觉设计和功…

论文解读《NewsBench:一个评估中文新闻大型语言模型编辑能力的系统评估框架》

引言&#xff1a;感觉这篇文章&#xff0c;对 LLMs 的新闻编辑能力做了一个详细的实验和分析&#xff0c;而且还贡献了一个宝贵的中文新闻数据集&#xff0c;蛮不错的&#xff0c;后面或许可以用起来&#xff0c;就拜读了一下。 这篇博客的题目说是解读&#xff0c;其实大部分…

赵进喜:不透析、不用肾移植,“三维护肾”巧治尿毒症

潜心研究中医药治疗尿毒症等慢性肾脏重症40余年来&#xff0c;北京名老中医&#xff0c;慢性肾病国医大师吕仁和教授医术传承人&#xff0c;全国优秀基层名中医赵进喜总结出弥足珍贵的重症良方&#xff0c;临床应用无数次守护近10万肾病重症患者生命。让仅有22岁的慢性肾衰尿毒…

DORIS - DORIS之倒排索引

什么是倒排索引&#xff1f; 倒排索引&#xff08;Inverted index&#xff09;&#xff0c;也常被称为反向索引、置入档案或反向档案&#xff0c;是一种索引方法&#xff0c;用于存储在全文搜索场景下某个单词在一个文档或者一组文档中的存储位置的映射&#xff0c;它是文档检…

AI开发-FAQ

1 需求 2 接口 3.1 pip下载指定版本 pip install package1.0.4 3.2 pip设置代理 pip install --proxyhttp://10.10.1.10:3128 somepackage 3.3 PyCharm设置代理 import os os.environ[http_proxy] http://your_proxy:port os.environ[https_proxy] http://your_proxy:portf…

java开发中间件学习记录(持续更新中~)

1 Redis 2JVM 3 java基础底层 4Mysql 5 spring 6 微服务 7.......(持续更新) One:Redis篇 1:Redis 1.穿透 1.1缓存穿透 1.1.1布隆过滤器 1.2缓存击穿 2&#xff1a;击穿 1.3&#xff1a;缓存雪崩 1.4:双写一致 1.5.持久化&#xff08;RDB,AOF&#xff09; 1.6…

80V降24V2A同步降压WT6037

80V降24V2A同步降压WT6037 WT6037是一款适用于36V-80V输入电压范围&#xff0c;输出24V2A电流的同步降压恒压芯片。该芯片具有宽输入电压范围&#xff0c;高转换效率&#xff0c;低静态电流消耗等特点&#xff0c;可广泛应用于电池组系统&#xff0c;电动自行车&#xff0c;电动…

SD-WAN网络如何实现双向访问?

在SD-WAN架构中&#xff0c;双向访问是一个重要的概念&#xff0c;它允许网络流量在不同方向上流动&#xff0c;从分支机构到数据中心或云端&#xff0c;再从数据中心或云端返回分支机构。本文将详细探讨SD-WAN如何实现双向访问&#xff0c;并解释其背后的工作原理。 什么是双向…

对话世优科技CEO纪智辉:AI模型让数字人发展按下加速键

2024年9月12日&#xff0c;中国国际服务贸易交易会全球服务贸易峰会在北京举行&#xff0c;世优科技作为深耕虚拟数字人领域的科技企业&#xff0c;聚焦“新而专”&#xff0c;连续两届参加服贸会。2024年&#xff0c;世优科技以合作供应商身份参与本届服贸会。 在AI的大浪潮下…

Jetpack Compose Side Effects in Details 副作用的详细信息

What is Side Effect’s? 副作用是什么&#xff1f; Side Effects is a change in the state of the application that occurs outside the scope of the composable function and is not related to the UI. In non-UI related state changes, our screen may recompose mor…