C++學習(線程相關)

目錄

一、線程庫thread

1.使用外部函數

2. 使用類的函數

3. 添加參數

二、線程庫 mutex

1.使用lock()方法

2.try_lock()方法

三、線程庫lock_guard

四、線程庫unique_lock

1.adopt_lock

2.defer_lock()

五、線程庫call_once

六、線程庫promise & future

七、condition變量使用場景

八、async 和 packaged_task

1.async

2.packaged_task


一、線程庫thread

1.使用外部函數

????????下面這段代碼的目的是等待子線程運行結束,因為可能存在主線程已經結束了,但是子線程還有程序要運行,此時直接return可能會出問題。

    t1.join();

2. 使用類的函數

#include<iostream>
#include<chrono>
#include<thread>
using namespace std;int i = 0;
void test1()
{while(i< 10){cout << "子線程運行中:" << i << endl;i++;this_thread::sleep_for(chrono::microseconds(10));}
}
class A
{private:int i = 0;public:void test2(){while(i< 10){cout << "子線程運行中:" << i << endl;i++;this_thread::sleep_for(chrono::microseconds(10));}}
};int main()
{A a;thread t1(&A::test2, &a);while(i< 10){cout << "主線程運行中:" << i << endl;i++;this_thread::sleep_for(chrono::microseconds(10));}t1.join();return 0;
}

3. 添加參數

#include<iostream>
#include<chrono>
#include<thread>
using namespace std;
int i = 0;
class A
{private:int i = 0;public:void test2(int num){while(i< 10){cout << "子線程運行中:num:" << num << endl;this_thread::sleep_for(chrono::microseconds(10));i++;}}
};int main()
{A a;thread t1(&A::test2, &a, 100);while(i< 10){cout << "主線程運行中:" << i << endl;i++;this_thread::sleep_for(chrono::microseconds(10));}t1.join();return 0;
}

二、線程庫 mutex

對于上面第一個的例子,存在主線程或者子線程打印一半,時間片結束,進入另外一個線程打印,導致亂碼,為了解決這個問題,引入鎖。

1.使用lock()方法

使用lock加鎖之后,當子線程執行一般,此時還沒釋放鎖,進入主線程,主線程也調用lock(),發現鎖已經被占用了,于是就等待,之后時間片到了進入子線程,子線程程序執行完畢后釋放鎖unlock()。

2.try_lock()方法

這個方法嘗試獲取鎖,成功獲得返回true,否則返回false,他不會阻塞,獲取不到鎖也可以做一些其他操作。

#include<iostream>
#include<chrono>
#include<thread>
#include<mutex>
using namespace std;
int i = 0;
mutex mtx;
void test2()
{while(i< 10){if(mtx.try_lock()){cout << "子線程運行中:" << i << endl;this_thread::sleep_for(chrono::microseconds(10000));i++;mtx.unlock();}else{cout << "子線程等待中:"<< endl;}}
}
int main()
{thread t1(test2);while(i< 10){if(mtx.try_lock()){cout << "主線程運行中:" << i << endl;i++;this_thread::sleep_for(chrono::microseconds(10000));mtx.unlock();}else{cout << "主線程等待中:"<< endl;}}t1.join();return 0;
}

三、線程庫lock_guard

上面每次都需要手動釋放,可能存在忘了釋放鎖,就會有bug,下面解決這個問題。本質上當這個變量作用域結束的時候執行析構函數,自動釋放鎖。

#include<iostream>
#include<chrono>
#include<thread>
#include<mutex>
#include<sstream>
using namespace std;int i = 0;
mutex mtx;// 輔助函數,用于獲取線程 ID 字符串
string getThreadId() {stringstream ss;ss << this_thread::get_id();return ss.str();
}void test2()
{while(i < 10){lock_guard<mutex> lock(mtx);cout << "子線程 " << getThreadId() << " 運行中:" << i << endl;this_thread::sleep_for(chrono::microseconds(10));i++;}
}int main()
{thread t1(test2);while(i < 10){lock_guard<mutex> lock(mtx);cout << "主線程 " << getThreadId() << " 運行中:" << i << endl;i++;this_thread::sleep_for(chrono::microseconds(10));}t1.join();return 0;
}

四、線程庫unique_lock

unique_lock提供了更高級的用法。它可以多傳一個參數,也可以不傳,不穿的用法和lock_guard一樣。

1.adopt_lock

它的作用是接管鎖,上面先創建一個鎖,之后由他接管,作用域結束的時候自動釋放。

#include<iostream>
#include<chrono>
#include<thread>
#include<mutex>
#include<sstream>
using namespace std;int i = 0;
mutex mtx;// 輔助函數,用于獲取線程 ID 字符串
string getThreadId() {stringstream ss;ss << this_thread::get_id();return ss.str();
}void test2()
{while(i < 10){mtx.lock();unique_lock<mutex> lock(mtx, adopt_lock);cout << "子線程 " << getThreadId() << " 運行中:" << i << endl;this_thread::sleep_for(chrono::microseconds(10));i++;}
}int main()
{thread t1(test2);while(i < 10){mtx.lock();unique_lock<mutex> lock(mtx, adopt_lock);cout << "主線程 " << getThreadId() << " 運行中:" << i << endl;i++;this_thread::sleep_for(chrono::microseconds(10));}t1.join();return 0;
}

2.defer_lock()

defer_lock的作用是延遲鎖,在后面調用lock.lock();才會獲取鎖和加鎖。

#include<iostream>
#include<chrono>
#include<thread>
#include<mutex>
#include<sstream>
using namespace std;int i = 0;
mutex mtx;// 輔助函數,用于獲取線程 ID 字符串
string getThreadId() {stringstream ss;ss << this_thread::get_id();return ss.str();
}void test2()
{while(i < 10){unique_lock<mutex> lock(mtx, defer_lock);lock.lock();cout << "子線程 " << getThreadId() << " 運行中:" << i << endl;this_thread::sleep_for(chrono::microseconds(10));i++;}
}int main()
{thread t1(test2);while(i < 10){unique_lock<mutex> lock(mtx, defer_lock);lock.lock();cout << "主線程 " << getThreadId() << " 運行中:" << i << endl;i++;this_thread::sleep_for(chrono::microseconds(10));}t1.join();return 0;
}

五、線程庫call_once

????????如果存在好幾個線程,調用一個函數,這個函數里面有個初始化操作,這個操作只需要被執行一次,就會用到下面的操作。

? ? ? ? 聲明once_flag, 之后將once_flag,init函數和以及init函數的參數傳遞給call_once。

六、線程庫promise & future

這個主要作用是異步獲取線程函數里面的數據。int sum = ft.get();這段代碼會阻塞,直到子線程設置ps.set_value(sum);。注意使用future<int> ft = ps.get_future();聲明的話,主線程只能get一次,如果想要get多次,那么使用shared_future<int> ft = ps.get_future();。

七、condition變量使用場景

? ? ? ? 生產者消費者模型,生產者不斷往隊列中添加任務,之后通知消費者取任務。

關鍵代碼解釋

cv.notify_one();? ?// 通知另外一個線程取任務

cv.wait(lck, []{return !q.empty();});? ? //? 這個鎖的參數很有必要,因為上面給鎖住了,所以需要先釋放了鎖才行,所以鎖也需要作為參數傳入,后面的就是條件,如果為True就等待。

#include<iostream>
#include<chrono>
#include<thread>
#include<mutex>
#include<queue>
#include<condition_variable>
using namespace std;queue<int> q;
condition_variable cv;
mutex mtx;
void Product()
{for(int i=0; i<10; i++){{unique_lock<mutex> lck(mtx);q.push(i);cv.notify_one();cout << "生產了" << i << endl << flush; }this_thread::sleep_for(chrono::milliseconds(5)); // 延長時間}
}void Consumer()
{while(true){unique_lock<mutex> lck(mtx);cv.wait(lck, []{return !q.empty();});int data = q.front();q.pop();cout << "消費了" << data << ",隊列大小: " << q.size() << endl << flush;if(data == -1) break;  // 正確退出this_thread::sleep_for(chrono::milliseconds(3)); }
}
void test2()
{   thread t2(Consumer);thread t1(Product);t1.join();// 添加退出條件,避免消費者線程無限循環{unique_lock<mutex> lck(mtx);q.push(-1); // 發送結束信號cv.notify_one();}t2.join();
}int main()
{test2();return 0;
}

八、async 和 packaged_task

他倆的作用都是異步獲取函數返回值。

1.async

關鍵代碼解釋:

future<int> f = async(add);? ? // 自動產生一個線程執行add這個函數

f.get()? // 讀取函數的返回值

2.packaged_task

關鍵代碼解釋:

packaged_task<int()> task(add);? ? ? // 創建一個packaged_task對象,不會創建線程

auto future_result = task.get_future();? ? // 得到這個任務的future對象

thread t(move(task));? ? ? // 根據任務創建線程,開始這行任務里面的函數

cout<<"sum = "<<future_result.get()<<endl;? ?// 等待函數執行完成,獲得返回值,對于future的get方法,如果函數沒有執行完成,就會阻塞。

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

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

相關文章

EPOLLONESHOT 深度解析:Linux epoll 的單次觸發機制

EPOLLONESHOT 深度解析&#xff1a;Linux epoll 的單次觸發機制 EPOLLONESHOT 是 Linux epoll 接口中的高級事件標志&#xff0c;用于實現精確的事件單次觸發控制。以下是其全面技術解析&#xff1a; 核心設計理念 #mermaid-svg-Xg5sCLdddqmKsvKG {font-family:"trebuchet…

深入解析MongoDB分片原理與運維實踐指南

深入解析MongoDB分片原理與運維實踐指南 技術背景與應用場景 隨著互聯網業務的高速發展&#xff0c;單節點MongoDB實例在數據量和訪問并發上都面臨瓶頸。為了解決數據存儲容量受限和讀寫性能下降的問題&#xff0c;MongoDB官方提供了分片&#xff08;Sharding&#xff09;方案&…

基于Django的天氣數據可視化分析預測系統

【86-Django】基于Django的天氣數據可視化分析預測系統&#xff08;完整系統源碼開發筆記詳細部署教程&#xff09;? 目錄 一、項目簡介 二、項目界面展示 三、項目視頻展示 四、技術架構 五、核心功能模塊 六、部署教程一、項目簡介 隨著全球氣候變化和極端天氣事件的頻發&am…

怎么放大單片機輸出電流

單片機作為電子系統的控制核心&#xff0c;其 I/O 口輸出電流通常較小&#xff08;一般在 10-20mA 左右&#xff09;&#xff0c;難以直接驅動繼電器、電機、大功率 LED 等需要較大工作電流的外設。因此&#xff0c;在實際應用中需通過特定電路放大單片機輸出電流&#xff0c;實…

站長百科類網站pbootcms模板(自適應手機端)+利于SEO優化(下載)

站長百科類網站pbootcms模板(自適應手機端)利于SEO優化 模板介紹&#xff1a; PbootCMS內核開發的模板&#xff0c;該模板屬于新聞資訊、新聞博客類企業使用&#xff01; 頁面簡潔簡單&#xff0c;容易管理&#xff0c;附帶測試數據&#xff01; 模板特點&#xff1a; 1、手工書…

【Golang】Go語言函數

Go語言函數 文章目錄Go語言函數Go函數特點一、函數的基本格式定義二、匿名函數三、自執行函數四、閉包函數五、延遲調用Go函數特點 無需聲明原型支持不定 變參支持多返回值支持匿名函數和閉包函數也是一種類型&#xff0c;一個函數可以賦值給變量不支持嵌套&#xff0c;一個包…

JAVA算法練習題day2

雙指針4.移動零二刷昨天的題&#xff0c;學習了新的數據結構StringBuilder。專為頻繁字符串拼接設計的可變字符串類。(https://blog.csdn.net/m0_73941339/article/details/145651287)二刷完昨天的題目&#xff0c;做到這題腦子已經轉不動了。做雙指針&#xff0c;一般雙指針初…

LLM2Rec-新國立-KDD2025-微調LLM獲得蘊含協同信息的embedding

文章目錄1. 背景與問題任務背景動機LLM2Rec 兩大步驟2. 方法2.1 Collaborative Supervised Fine-tuning&#xff08;CSFT&#xff09;2.2 Item-level Embedding Modeling2.2.1 從單向注意力 → 雙向注意力&#xff08;Bidirectional attention&#xff09;2.2.2 商品級別的對比…

前端學習9:JavaScript--對象與原型

前言&#xff1a;適合有基礎的同學入門嘗試 / 復習回憶。對象基礎&#xff1a;1.創建用戶對象const user {// 屬性&#xff08;鍵值對&#xff09;name: "小島",age: 20,isAdmin: false, }2.方法&#xff08;函數屬性&#xff09;sayHello() {console.log(你好&…

網絡:應用層

網絡&#xff1a;應用層 我們要知道&#xff0c;所有的問題解決都是在應用層。:happy: 協議是一種約定&#xff0c;也就是雙方約定好的結構化的數據。但是在讀寫數據時我們都是按字符串的方式來發送接受的&#xff0c;那么我們應該如和傳輸結構化的數據呢&#xff1f;應用層協…

rust-包和箱子

&#x1f4e6; 圖解 Rust 代碼組織層級 #mermaid-svg-fBDy1PDZZ6bi000z {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-fBDy1PDZZ6bi000z .error-icon{fill:#552222;}#mermaid-svg-fBDy1PDZZ6bi000z .error-text{fi…

C++算法競賽篇(五)循環嵌套題型講解

C算法競賽篇&#xff08;五&#xff09;循環嵌套題型講解前言C循環嵌套題型講解第一題 包含數字的9第二題 求出 e 的值第三題 斐波那契數列第四題 第 n 小的質數第五題 水仙花數前言 前面的題型里我們認識了C里面的三大循環本篇博客我們開始講解C循環嵌套題型 我的個人主頁&am…

Gradio全解8——ChatInterfaceChatbot:聊天界面類與聊天機器人(3)——ChatInterface的多模態功能與附加輸入輸出

Gradio全解8——ChatInterface&Chatbot&#xff1a;聊天界面類與聊天機器人&#xff08;3&#xff09;——ChatInterface的多模態功能與附加輸入輸出8.3 ChatInterface的多模態功能與附加輸入輸出8.3.1 多模態功能1. 設置multimodal和fn參數2. 傳入MultimodalTextbox組件及…

php算法-- 關聯數組使用,優化sip賬號去重

文章目錄1 變量定義2. 核心特性code1 變量定義 類型&#xff1a;嵌套的關聯數組&#xff08;Nested Associative Array&#xff09;外層結構&#xff1a;[中繼ID > 賬號列表]鍵 (Key)&#xff1a;中繼ID&#xff08;字符串或整型&#xff09;值 (Value)&#xff1a;索引數組…

LLM 多語言數據集

多語言數據感覺主要還是fineweb和fineweb2, 其他數據都是主要針對特定語種比較多 101 Billion Arabic Words Dataset ClusterlabAi/101_billion_arabic_words_dataset 數據主要從e Common Crawl WET 中提取&#xff0c;并采用了創新的技術來進行去重和篩選&#xff0c;主要解決…

【HarmonyOS Next之旅】DevEco Studio使用指南(三十六) -> 配置構建(三)

目錄 1 -> 定制HAR多目標構建產物 1.1 -> 定義產物的deviceType 1.2 -> 定義C工程依賴的.so文件 1.3 -> 定義產物的資源 2 -> 配置APP多目標構建產物 2.1 -> 定義產物的APP包名和供應商名稱 2.2 -> 定義product的bundleName 2.3 -> 定義produc…

數據賦能(340)——技術平臺——共享平臺

概述重要性如下&#xff1a;提高數據利用效率&#xff1a;數據共享平臺能夠將分散在各部門的數據進行集中管理&#xff0c;促進數據流通和共享&#xff0c;避免數據孤島現象&#xff0c;從而提高數據利用效率。促進決策科學化&#xff1a;通過共享平臺&#xff0c;各部門可以獲…

開閉原則在C++中的實現

開閉原則&#xff08;Open/Closed Principle&#xff0c;簡稱 OCP&#xff09;是面向對象設計中的一個重要原則&#xff0c;屬于“SOLID”原則之一。它的核心思想是&#xff1a;“軟件實體&#xff08;如類、模塊、函數等&#xff09;應該對擴展開放&#xff0c;對修改關閉。”…

C語言:*p++與p++有何區別

1. 指針基礎練習&#xff1a;演示p、p和(*p)的區別核心目的&#xff1a;區分指針自增與指針指向值自增的不同邏輯&#xff0c;理解運算符優先級對指針操作的影響。#include <stdio.h>void arr1() {int arr[] {11,13,15,17,19};int *p arr;printf("結果1&#xff1…

【設計】設計一個web版的數據庫管理平臺后端(之二)

在之前&#xff0c;我寫過一篇【設計】設計一個web版的數據庫管理平臺后端精要 的文章&#xff0c;文章講了一個web版數據庫管理平臺的實現思路及主要代碼。 最近&#xff0c;我看了下Mybatis的源碼&#xff0c;覺得Mybatis的分層架構挺好&#xff0c;所以想到了完善下web版數據…