C++11條件變量condition_variable

文章目錄

    • 前言
    • 正文
      • 等待
      • 通知
      • 注意事項
    • 結尾

前言

條件變量用于多線程中,其作用是在多線程間實現線程的等待、喚醒和通知機制,常配合互斥鎖(std::mutex)一起使用。它主要用于解決數據競爭問題>。

正文

條件變量只有五個函數:

方法作用
notify_one()通知一個等待的線程
notify_all()通知所有等待的線程
wait()阻塞該線程,直到條件變量被喚醒
wait_for()阻塞該線程,直到條件變量被喚醒或者到達指定時限時長后
wait_until()阻塞該線程,直到條件變量被喚醒或者到達指定時間點后

條件變量的方法分為兩種:通知等待,我們一個個來說:

等待

wait()部分的就是等待函數,它接收兩個參數:

template<class Predicate>
void wait(std::unique_lock<std::mutex>& lock, Predicate pred);void wait(std::unique_lock<std::mutex>& lock);

它有兩個版本,我們先說最簡單的版本,它只有一個參數:

void wait(std::unique_lock<std::mutex>& lock);

它接收一個unique_lock作為參數。當程序運行到wait()這一行的時候,程序必定阻塞,只有等到通知之后才會繼續運行,這個狀態我們也稱之為睡眠
那么有兩個參數的呢?它的第二個參數是一個謂詞,這里我們能夠理解為一個函數,通常是使用lambda表達式。當wait()接到通知的時候,執行這個謂詞,若是返回的結果為true,就獲取鎖的所有權,執行接下來的語句;若是為false,它就重新進入睡眠狀態,繼續阻塞線程,等待下一次通知的出現。
所以謂詞的聲明也等同于:

bool pred();

那么其他的wait就不多說了。

通知

通知有兩個函數,notify_one()和notify_all(),前者只通知一個線程,而后者則會通知所有線程,在通知之后,被通知的線程會判斷是否滿足條件函數的要求,若是符合要求,則執行其后面的函數,若是不滿足要求,則回到睡眠狀態。

注意事項

notify_one() 和 notify_all() 的調用都不會立即執行實際的喚醒操作。相反,它們只是在條件變量上設置了一個喚醒標志,并在互斥鎖釋放之后,等待其他線程重新獲取互斥鎖時才會實際執行喚醒操作。
也就是說:只有能獲取到互斥鎖的時候才會進行喚醒,并讓它去爭搶互斥鎖。

結尾

條件變量的內容其實很少,也比較好理解,問題在怎么去使用它。
這里我給出一段代碼,這段代碼是一個簡單的消息隊列,也是個非常簡單的生產者消費者隊列,實現了一個消息的發送和接收功能,配合代碼食用效果更佳(在重要的地方我都寫了注釋,希望能夠幫助大家理解):

#include <iostream>
#include <thread>
#include <memory>
#include <string>
#include <condition_variable>
#include <list>
#include <atomic>std::mutex mtx;
std::condition_variable cv;
std::list<std::string> msg;// 讀取數據
void read_thread(){while(true){std::unique_lock<std::mutex> lock(mtx);// 阻塞等待消息(并且解鎖)// 有消息再執行,沒消息不執行cv.wait(lock,[&](){ return !msg.empty(); });// 獲取到互斥鎖std::cout << "收到消息,解析中:" << std::endl;std::cout << msg.front() << std::endl;msg.pop_front();}
}// 寫入數據
void write_thread(){std::cout << "請輸入需要發送的數據:" << std::endl;std::string input;while(true){if(std::cin >> input){std::unique_lock<std::mutex> lock(mtx);msg.push_back(input);std::cout << "數據成功輸入" << std::endl;// 通知read線程,有消息可以接收cv.notify_all();}}
}int main(){std::thread write_(write_thread);write_.detach();std::thread read_(read_thread);read_.detach();// 阻塞主線程while(true);return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/207646.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/207646.shtml
英文地址,請注明出處:http://en.pswp.cn/news/207646.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PyQt6 QCalendarWidget日歷控件

?鋒哥原創的PyQt6視頻教程&#xff1a; 2024版 PyQt6 Python桌面開發 視頻教程(無廢話版) 玩命更新中~_嗶哩嗶哩_bilibili2024版 PyQt6 Python桌面開發 視頻教程(無廢話版) 玩命更新中~共計39條視頻&#xff0c;包括&#xff1a;2024版 PyQt6 Python桌面開發 視頻教程(無廢話…

快速實現入門HarmonyOS開發

本文檔適用于HarmonyOS應用開發的初學者。編寫兩個簡單的頁面&#xff0c;實現在第一個頁面點擊按鈕跳轉到第二個頁面。開始前&#xff0c;請參考下載與安裝軟件、配置開發環境和運行HelloWorld&#xff0c;完成開發工具的安裝和開發環境的配置。 開發Ability 概述&#xff1…

Python 日期時間模塊詳解(datetime)

文章目錄 1 概述1.1 datetime 類圖1.2 類描述 2 常用方法2.1 獲取當前日期時間&#xff1a;now()、today()、time()2.2 日期時間格式化&#xff1a;strftime()2.3 日期時間大小比較&#xff1a;>、、<2.4 日期時間間隔&#xff1a;- 3 擴展3.1 Python 中日期時間格式化符…

混合預編碼(Hybrid Precoding)的全連接結構與子連接結構

A Survey on Hybrid Beamforming Techniques in 5G: Architecture and System Model Perspectives 全連接結構的混合預編碼 子連接結構的混合預編碼 Alternating Minimization Algorithms for HybridPrecoding in Millimeter Wave MIMO Systems

UE Websocket筆記

參考鏈接 [UE4 C入門到進階]12.Websocket網絡通信 - 嗶哩嗶哩 包含怎么用Nodejs 寫測試服務器 UE4_使用WebSocket和Json&#xff08;上&#xff09; - 知乎 包含Python寫測試服務器 UE4_使用WebSocket和Json&#xff08;下&#xff09; - 知乎 示例代碼 xxx.Build.cs"W…

【React】使用react hooks實現評論示例

實現功能 1、渲染評論列表 2、刪除評論 3、渲染導航欄和高亮 4、評論列表排序功能 5、獲取評論 6、點擊發布按鈕發布評論 7、清空輸入框 8、重新聚焦 實現代碼 1、需要引入 import React, { useRef, useState } from react import avatar from "../logo.png" //頭…

[動態規劃及遞歸記憶搜索法]2.插入乘號

插入乘號 題目描述 給定一個非負整數&#xff0c;用k個乘號將其分割&#xff0c;使得乘積最大。 例如&#xff1a;在整數12345中插入兩個乘號&#xff0c;有以下插入法&#xff1a; 1*2*345 1*23*45 1*234*5 12*3*45 12*34*5 123*4*5 其中最大值是123*4*5 2460 關于輸入 一…

前端小技巧: 面向切面編程在前端代碼中的應用

面向切面編程 面向切面編程在java中提出這類概念但是在js沒有束縛和約定&#xff0c;只需要按編程思想來實現原理在js中使用function或class實現面向切面編程 面向切面概念 AOP (Aspect Oriented Programming) 面向切面編程主要實現目的是針對業務處理過程中的切面進行提取&…

第18章:隨堂復習與企業真題(JDK8-17新特性)

第18章&#xff1a;隨堂復習與企業真題&#xff08;JDK8-17新特性&#xff09; 一、隨堂復習 1. JDK新特性的概述 幾個重要的版本 jdk 5.0 / jdk 8.0 &#xff1a;里程碑式的版本jdk9.0 開始每6個月發布一個新的版本LTS : jdk8 、 jdk 11 、 jdk 17 如何學習新特性 > 角…

Android安全學習路標

1. Android操作系統基礎知識 首先&#xff0c;你需要建立堅實的Android操作系統基礎知識&#xff0c;包括Android架構、進程和內存管理、應用組件和權限模型等基本概念。 2. 安全防范理論 學習關于安全防范理論的基礎知識&#xff0c;包括常見的威脅模型、攻擊類型和安全風險…

Python-猜數字游戲

&#x1f388; 博主&#xff1a;一只程序猿子 &#x1f388; 博客主頁&#xff1a;一只程序猿子 博客主頁 &#x1f388; 個人介紹&#xff1a;愛好(bushi)編程&#xff01; &#x1f388; 創作不易&#xff1a;喜歡的話麻煩您點個&#x1f44d;和?&#xff01; &#x1f388;…

免費的AI改寫文案軟件,熱門AI改寫文案軟件【2024】

在數字化時代&#xff0c;文案創作變得更為便捷&#xff0c;其中AI改寫文案軟件的興起為寫作者們帶來了全新的創作體驗。這些工具通過智能算法和自然語言處理技術&#xff0c;能夠快速改寫文本&#xff0c;提高創作效率。本文將深入探討AI改寫文案軟件的現狀&#xff0c;介紹一…

LeetCode題:174. 地下城游戲

目錄 一、題目要求 二、解題思路 &#xff08;1&#xff09;狀態表示 &#xff08;2&#xff09;狀態轉移方程 &#xff08;3&#xff09;初始化dp表 &#xff08;4&#xff09;填表順序 &#xff08;5&#xff09;返回值 三、代碼 一、題目要求 174. 地下城游戲 惡魔們…

swagger入門

swagger入門 pom依賴 不用專門導入swagger 因為springboot已經將它集成了 org.springframework.boot spring-boot-starter com.github.xiaoymin knife4j-spring-boot-starter Swagger配置類 Configuration public class SwaggerConfig { // 創建并配置Docket Bean&#xf…

snakeyaml編輯yaml文件并覆蓋注釋

文章目錄 前言技術積累實戰演示1、引入maven依賴2、覆蓋注釋工具類3、snakeyaml工具類4、測試用例5、測試效果展示 寫在最后 前言 最近在做一個動態整合框架的項目&#xff0c;需要根據需求動態組裝各個功能模塊。其中就涉及到了在application.yaml中加入其他模塊的配置&#…

TCP傳輸層詳解(計算機網絡復習)

介紹&#xff1a;TCP/IP包含了一系列的協議&#xff0c;也叫TCP/IP協議族&#xff0c;簡稱TCP/IP。該協議族提供了點對點的連接機制&#xff0c;并將傳輸數據幀的封裝、尋址、傳輸、路由以及接收方式都予以標準化 TCP/IP的分層模型 在講TCP/IP協議之前&#xff0c;首先介紹一…

力扣貪心題解 跳躍游戲

55. 跳躍游戲 - 力扣&#xff08;LeetCode&#xff09; 給你一個非負整數數組 nums &#xff0c;你最初位于數組的 第一個下標 。數組中的每個元素代表你在該位置可以跳躍的最大長度。 判斷你是否能夠到達最后一個下標&#xff0c;如果可以&#xff0c;返回 true &#xff1b…

信息系統開發方法

企業信息系統對于企業信息化的重要意義是不言而喻的。從實際運行的效果來看&#xff0c;有些信息系統運行得很成功&#xff0c;取得了巨大的經濟效益和社會效益&#xff1b;但也有些信息系統效果并不顯著&#xff0c;甚至還有個別信息系統開始時還能正常運行&#xff0c;可時間…

廣州數字孿生賦能工業制造,加速推進制造業數字化轉型

廣州數字孿生賦能工業制造&#xff0c;加速推進制造業數字化轉型。數字孿生系統基于歷史數據、實時數據&#xff0c;采用人工智能、大數據分析等新一代信息技術對物理實體的組成、特征、功能和性能進行數字化定義和建模。通過構建在信息世界對物理實體的等價映射&#xff0c;對…

Axure官方軟件安裝、漢化保姆級教程(帶官方資源下載)

1.下載漢化包 百度云鏈接&#xff1a;https://pan.baidu.com/s/1lluobjjBZvitASMt8e0A_w?pwdjqxn 提取碼&#xff1a; jqxn 2.解壓壓縮包 3.安裝Axure 進行安裝 點擊next 打勾&#xff0c;然后next, 默認是c盤&#xff0c;修改成自己的文件夾&#xff08;不要什么都放c盤里…