C++多線程同步(上)

多線程同步

  • 引言
  • 總述
  • 詳情
    • 互斥鎖
      • 示例
      • 運行結果
      • 分析
    • 條件變量
      • 示例一
        • 實現
        • 分析
        • 優化
        • 運行結果
      • 示例二
        • 實現代碼
        • 運行結果
      • 示例三
        • 實現代碼
        • 運行結果
    • 讀寫鎖
      • 示例
        • 實現代碼
        • 注意
        • 分析
        • 運行結果
      • 附言
        • 實現
        • 運行結果
        • 運行結果
        • 個人心得

引言

項目中使用多線程,會遇到兩種問題,一種是對共享資源的訪問時需要考慮多線程競爭訪問導致的不是預期的結果,另一種是多線程之間需要同步的問題。其實質歸根結底就是多線程之間的同步。
本文主要在C++11的基礎之上,結合示例講述多線程同步的幾種方法。
本文為上篇。

總述

C++中多線程同步的方式分為:
互斥鎖,條件變量,讀寫鎖,信號量,future和promise,原子操作,線程局部存儲

詳情

下面根據上面提到的七種線程同步的方式分別給出示例。

互斥鎖

互斥鎖用于解決多線程間對共享資源的競爭問題,具有排它性。一旦一個線程獲取鎖,并加鎖,其他的線程只能阻塞等待該線程解鎖之后再搶占鎖,且每次只能有一個線程獲得鎖,沒有獲得鎖的線程只能阻塞等待。

示例

下面是互斥鎖的示例:

#include <iostream>
#include <thread>
#include <mutex>using namespace std;
mutex g_mutex;void fun(int n,const char& c) {g_mutex.lock();cout << "子線程的線程id:" <<this_thread::get_id()<<"開始執行該線程......"<< endl;for (int i = 0; i < n;++i) {cout << c;}cout << endl;cout << this_thread::get_id()<<"子線程結束" << endl;g_mutex.unlock();
}int main()
{thread t1(fun,5,'S');thread t2(fun,6,'*');t1.join();t2.join();cout << "主線程的id:" << this_thread::get_id() << endl;return 0;
}

運行結果

在這里插入圖片描述

分析

上面的示例創建了兩個子線程,執行相同的線程處理函數,這就涉及到多線程對共享資源的競爭問題,這里兩個子線程都搶著調用線程處理函數fun。由于何時加鎖,在哪里加鎖,需要結合開發人員的實際需求而定。這個示例希望程序能夠輸出完整的一個子線程調用fun函數后的內容,所以在剛進入線程處理函數和離開線程處理函數的時候進行加鎖和解鎖。

若是希望只給fun函數中的循環打印部分加鎖,可以這樣修改(只修改線程處理函數fun加鎖,解鎖位置,其它不變):

void fun(int n,const char& c) {cout << "子線程的線程id:" <<this_thread::get_id()<<"開始執行該線程......"<< endl;g_mutex.lock();for (int i = 0; i < n;++i) {cout << c;}g_mutex.unlock();cout << endl;cout << this_thread::get_id()<<"子線程結束" << endl;
}

執行的結果:
在這里插入圖片描述
可以看到上面的示例,變動了加鎖和解鎖的位置之后,很明顯的出現了資源競爭,輸出后結果出現了混亂。當然輸出結果也會出現很多種,無法確定。像下面這樣,是再次運行被修改加鎖和解鎖的位置之后的運行結果。
在這里插入圖片描述
也可能是這樣的運行結果:
在這里插入圖片描述
對于加鎖的部分,當前獲取鎖的子線程可以保證其連續執行,但是不加鎖的部分就會出現資源競爭搶占,最終兩個子線程的同一個線程處理函數fun中不加鎖的內容會穿插著輸出,達不到想要的效果。

條件變量

條件變量需要與互斥鎖搭配使用來達到想要的效果。

示例一

實現

下面是實現代碼:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>using namespace std;
mutex g_mutex;
condition_variable g_cond;
bool IsReady = false;
const int g_num = 10;void fun(int n) {unique_lock<mutex> lock(g_mutex);while (!IsReady) {cout << "線程被阻塞....." << endl;g_cond.wait(lock);}cout << "線程" <<this_thread::get_id()<<"執行完成!"<< endl;
}void wakeUp() {this_thread::sleep_for(chrono::milliseconds(2));//延遲2毫秒,為了讓子線程出現阻塞等待的過程unique_lock<mutex> lock(g_mutex);IsReady = true;cout 

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

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

相關文章

關于運行flutter app 運行到模擬器出現異常提示

Exception: Gradle task assembleDebug failed with exit code 1 解決方案&#xff1a; 1.講當前文件的distributionUrl值改為 https://mirrors.cloud.tencent.com/gradle/gradle-7.4-all.zip

Redis 學習筆記 3:黑馬點評

Redis 學習筆記 3&#xff1a;黑馬點評 準備工作 需要先導入項目相關資源&#xff1a; 數據庫文件 hmdp.sql后端代碼 hm-dianping.zip包括前端代碼的 Nginx 啟動后端代碼和 Nginx。 短信登錄 發送驗證碼 PostMapping("code") public Result sendCode(RequestP…

超市售貨|超市售貨管理小程序|基于微信小程序的超市售貨管理系統設計與實現(源碼+數據庫+文檔)

超市售貨管理小程序目錄 目錄 基于微信小程序的超市售貨管理系統設計與實現 一、前言 二、系統功能設計 三、系統實現 1、微信小程序前臺 2、管理員后臺 &#xff08;1&#xff09;商品管理 &#xff08;2&#xff09;出入庫管理 &#xff08;3&#xff09;公告管理 …

CrossOver2024虛擬機軟件的優缺點分別是什么?

CrossOver虛擬機軟件的優缺點分別如下&#xff1a; 優點&#xff1a; 無需雙系統&#xff1a;用戶可以在Mac或Linux系統上直接運行Windows應用程序&#xff0c;無需安裝雙系統&#xff0c;從而節省了硬盤空間并避免了系統切換的麻煩。易于安裝和使用&#xff1a;CrossOver具有…

文件上傳---->生僻字解析漏洞

現在的現實生活中&#xff0c;存在文件上傳的點&#xff0c;基本上都是白名單判斷&#xff08;很少黑名單了&#xff09; 對于白名單&#xff0c;我們有截斷&#xff0c;圖片馬&#xff0c;二次渲染&#xff0c;服務器解析漏洞這些&#xff0c;于是今天我就來補充一種在upload…

RAW 編程接口 TCP 簡介

一、LWIP 中 中 RAW API 編程接口中與 TCP 相關的函數 二、LWIP TCP RAW API 函數 三、LwIP_Periodic_Handle函數 LwIP_Periodic_Handle 函數是一個必須被無限循環調用的 LwIP支持函數&#xff0c;一般在 main函數的無限循環中調用&#xff0c;主要功能是為 LwIP各個模塊提供…

web前端安全性——JSONP劫持

1、JSONP概念 JSONP(JSON with Padding)是JSON的一種“使用模式”&#xff0c;可用于解決主流瀏覽器的跨域數據訪問的問題。由于同源策略&#xff0c;協議IP端口有任意不同都會導致請求跨域&#xff0c;而HTML的script元素是一個例外。利用script元素的這個開放策略&#xff0…

vscode【報錯】yarn : 無法將“yarn”項識別為 cmdlet

問題 CMD下載完yarn可以查看到yarn版本&#xff0c;但是進入到vscode控制臺報錯無法識別&#xff0c;報錯內容如下&#xff1a; vscode【報錯】yarn : 無法將“yarn”項識別為 cmdlet、函數、腳本文件或可運行程序的名稱。請檢查名稱的拼寫&#xff0c;如果包括路徑&#xff…

@ 代碼隨想錄算法訓練營第8周(C語言)|Day57(動態規劃)

代碼隨想錄算法訓練營第8周&#xff08;C語言&#xff09;|Day57&#xff08;動態規劃&#xff09; Day53、動態規劃&#xff08;● 1143.最長公共子序列 ● 1035.不相交的線 ● 53. 最大子序和 動態規劃 &#xff09; 1143.最長公共子序列 題目描述 給定兩個字符串 text1 …

C#面:i++ 和 ++i 的區別

i 先參與左邊的運算&#xff0c;之后 i 自增&#xff1b; int i 5; int result i; // result的值為5&#xff0c;i的值變為6 i i 先自增&#xff0c;之后的值&#xff0c;參與左邊的運算&#xff1b; int i 5; int result i; // result的值為6&#xff0c;i的值也為6…

【一步步由簡入深,搞定FFT,持續更新中...】

作為一個傾向于形象思維的工程師&#xff0c;總想把復雜深奧的知識搞的方便理解&#xff0c;雖然上學時學過數字信號處理&#xff0c;仍然一知半解&#xff0c;現在想借著項目中涉及到的頻譜相關知識總結下來&#xff0c;在了解中逐步完善。 好了&#xff0c;首先要明確的概念是…

ffmpeg for android編譯全過程與遇到的問題

編譯前準備 編譯環境&#xff1a;Ubuntu16&#xff0c;可自行下載VMWare最新版并百度永久許可證或在服務器上安裝Ubuntu ffmpeg源碼&#xff1a;ffmpeg4.2.2 NDK下載&#xff1a;Android NDK r21e 有條件的最好還是在Liunx平臺下編譯吧&#xff0c;Windows平臺下編譯坑更多…

【計算機網絡】數據鏈路層|封裝成幀|透明傳輸|差錯檢測|PPP協議|CSMA/CD協議

目錄 一、思維導圖 ? 二、數據鏈路層功能概述 1.數據鏈路層概述 2.數據鏈路層功能概述——封裝成幀 3.數據鏈路層功能概述——透明傳輸 4.數據鏈路層功能概述——差錯檢測 三、數據鏈路層重要協議 1.數據鏈路層重要協議&#xff1a;PPP協議 2.數據鏈路層重要協議&#x…

js設計模式:備忘錄模式

作用: 封裝的對象可以在對象觸發行為時進行狀態的記錄與保存 也可以進行狀態的回退,恢復之前的狀態 示例: class Editor{constructor(){this.allText }edit(text){this.allText text}saveNow(){return new EditorText(this.allText)}backspacing(editorText){this.allText…

護眼臺燈哪個品牌更好用?五大好用護眼臺燈大爆料!

護眼臺燈相信大家都有所耳聞或者使用過,家里有小孩的可能了解更深,畢竟是孩子學習時需要使用的小家電。現在市面上的護眼臺燈種類可以說是多到眼花繚亂,甚至有些劣質的產品摻雜在里面,或許有些寶媽已經踩過一些坑了&#xff0c;護眼臺燈究竟哪個品牌更好用&#xff1f; &#x…

這個春節,爽了

四次醫院 請了一周假&#xff0c;準備開始愉快的長假。 結果第一天小孩就發燒了&#xff0c;趕緊送醫院拿藥。回到家才發現&#xff0c;給醫生看的驗血報告是上一次的&#xff0c;那是好幾個月之前的。 但是藥已經吃了&#xff0c;這是吃錯藥了呀&#xff01;&#xff01; …

手機中有哪些逆向進化的功能

手機中有哪些逆向進化的功能&#xff1f;逆向進化是指明明很優秀的很方便的功能&#xff0c;卻因為成本或者其他工業原因莫名其妙地給取消了。 逆向進化1&#xff1a;可拆卸電池-變為不可拆卸電池。 智能手機為了追求輕薄等原因&#xff0c;所以移除了可拆卸電池功能。將電池…

GoLand 相關

goland 下載依賴 go mod tidy&#xff1a;保持依賴整潔 go mod tidy 命令的作用是清理未使用的依賴&#xff0c;并更新 go.mod 以及 go.sum 文件。 go mod tidy 和 go mod vendor 兩個命令是維護項目依賴不可或缺的工具。go mod tidy 確保了項目的 go.mod 文件精簡且準確&…

ubuntu20.04安裝實時內核補丁PREEMPT_RT

參考&#xff1a; Ubuntu 18.04安裝 RT-PREEMPT 實時內核及補丁【過程記錄】_ubuntu18.04 preempt rt linux 5.6.19-CSDN博客 https://github.com/UniversalRobots/Universal_Robots_ROS_Driver/blob/master/ur_robot_driver/doc/real_time.md當前內核&#xff1a;5.15.0-94-ge…

1.deeplabv3+網絡結構及原理

這里的網絡結構及原理可以看這篇博客&#xff0c;DeepLabV3: 在DeepLabV3基礎上引入了Decoder_matlab deeplabv3resnet101-CSDN博客該博客翻譯原論文解釋得很清楚。 一、引言 語義分割的目標是為圖像中的每個像素分配語義標簽。在這項研究中&#xff0c;考慮了兩種類型的神經網…