C++ 多線程簡要講解

? ? ? ? std::thread是 C++11 標準庫中用于多線程編程的核心類,提供線程的創建、管理和同步功能。下面我們一一講解。

一.構造函數

官網的構造函數如下:

1.默認構造函數和線程創建

thread() noexcept;

作用:創建一個?std::thread?對象,但不關聯任何實際線程?(即空線程對象)。

如:

std::thread t;  // 空線程對象,不執行任何操作

注意:空線程對象不可調用?join()?或?detach(),需先綁定有效線程。

2.初始化構造函數

template <class Fn, class... Args>
explicit thread(Fn&& fn, Args&&... args);
  • 作用創建一個新線程,新線程會立即執行?fn(args...)函數
  • ?參數
    • fn:可調用對象(函數、Lambda、函數對象等)。
    • args:傳遞給?fn?的參數

如:?

void print(int x) { std::cout << x; }
std::thread t(print, 42);  // 線程執行 print(42)
t.join();

?這里要注意下面幾點

  • explicit?禁止隱式類型轉換(如避免誤將函數指針轉線程對象)。
  • 參數默認按值拷貝傳遞,若需傳引用需用?std::ref
  • 示例:
int x = 42;
std::thread t([](int& v) { v++; }, std::ref(x));  // 傳遞引用

3.拷貝構造函數(被刪除)?

thread(const thread&) = delete;?

  • ?作用:禁止拷貝構造線程對象(線程資源不可復制)。
  • 示例:
  • std::thread t1([]{ /* ... */ });
    std::thread t2 = t1;  // 編譯錯誤!拷貝構造被禁用
  • ?原因:線程是獨占資源,拷貝可能導致線程重復管理(如多次?join())。

?4.移動構造函數

thread(thread&& x) noexcept;
  • ?作用:將線程所有權從?x?轉移到新對象(x?變為空線程對象)。
  • ?示例
    std::thread t1([]{ /* ... */ });
    std::thread t2 = std::move(t1);  // t1 變為空,t2 接管線程
    t2.join();

這里要注意下面幾點:

  • 移動后,原線程對象?x?不再關聯任何線程。
  • 用于將線程對象存入容器或轉移所有權:std::vector<std::thread> threads; threads.push_back(std::thread([]{ /* ... */ })); // 必須用移動語義
std::vector<std::thread> threads;
threads.push_back(std::thread([]{ /* ... */ }));  // 必須用移動語義

?二.賦值運算符重載

1. 移動賦值運算符(Move Assignment)

thread& operator=(thread&& rhs) noexcept;

  • ?關鍵行為
    • 當前對象會先釋放自己原本持有的線程資源(如果存在)。
    • 接管?rhs?的線程所有權,rhs?變為空線程對象?(不再關聯任何線程)。
    • 操作是原子的,且標記為?noexcept(保證不拋出異常)。
  • ?示例
    std::thread t1([]{ /* 任務 1 */ });
    std::thread t2;
    t2 = std::move(t1);  // t1 的線程所有權轉移給 t2,t1 變為空
    t2.join();
  • ?典型用途
    • 將線程對象存入容器(如?std::vector<std::thread>)。
    • 動態管理線程所有權(如線程池)。

?2. 拷貝賦值運算符(被刪除)?

thread& operator=(const thread&) = delete;

  • ?作用:?禁止拷貝賦值?(編譯時報錯)。
  • ?原因
    • 線程是獨占資源,拷貝會導致多個對象管理同一線程,引發重復?join()?或?detach()
    • 保證線程對象的唯一所有權,避免資源管理沖突。
  • ?錯誤示例
    std::thread t1([]{ /* ... */ });
    std::thread t2;
    t2 = t1;  // 編譯錯誤!拷貝賦值被禁用

??三.線程等待和線程分離

????????線程等待就是讓主線程等待子線程執行完畢,首先我們要明白為什么要進行線程等待

1.主線程是進程的入口,若主線程執行完畢,操作系統會直接終止整個進程(包括所有子線程),無論子線程是否完成任務。

2.子線程可能持有共享資源(如內存、文件句柄、網絡連接),若主線程不等待子線程結束就退出,可能導致:資源泄漏?(如未關閉的數據庫連接)和數據競爭?(子線程訪問已被主線程釋放的內存,導致崩潰)。

3.部分情況下線程執行計算或數據處理后,主線程需要匯總結果

????????線程分離就是用于解除線程與其創建者(如主線程)的關聯,使得子線程在終止后能夠自動釋放資源,無需其他線程顯式調用?join()?等待或回收。

????????下面我們就來講解一下線程等待和線程分離函數join()?和?detach()

join():在主線程中調用阻塞主線程,直到當前線程執行完畢,就是讓主線程等待子線程執行完畢

detach():分離線程,使其在后臺獨立運行(無法再管理)。

必須在?std::thread?對象銷毀前調用?join()?或?detach(),否則程序終止。

std::thread t([]{ /* ... */ });if (t.joinable()) {t.join();   // 或 t.detach();
}

四.線程 ID 和命名

  • ?get_id():獲取線程唯一標識符。
  • ?std::this_thread?命名空間提供當前線程操作。有get_id(),yield(),sleep_for()等操作。
std::thread t([]{ std::cout << "Thread ID: " << std::this_thread::get_id() << "\n";
});
std::cout << "Main thread ID: " << t.get_id() << "\n";
t.join();

五.線程中的同步機制

1. 互斥量?std::mutex

防止多個線程同時訪問共享資源。

std::mutex mtx;
int counter = 0;void safe_increment() {std::lock_guard<std::mutex> lock(mtx); // 自動加鎖解鎖counter++;
}std::thread t1(safe_increment);
std::thread t2(safe_increment);
t1.join(); t2.join();

2. 條件變量?std::condition_variable

用于線程間的條件同步。

std::mutex mtx;
std::condition_variable cv;
bool ready = false;void wait_thread() {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, []{ return ready; }); // 等待條件滿足std::cout << "Ready!\n";
}void signal_thread() {std::this_thread::sleep_for(std::chrono::seconds(1));{std::lock_guard<std::mutex> lock(mtx);ready = true;}cv.notify_one(); // 通知等待線程
}std::thread t1(wait_thread);
std::thread t2(signal_thread);
t1.join(); t2.join();

六.實踐操作:

用兩個線程分別交替打印 1-100 的奇數和偶數,通過互斥鎖和條件變量實現交替輸出:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>using namespace std;int num = 1;                        // 共享計數器
mutex mtx;                          // 互斥鎖
condition_variable cv;              // 條件變量
const int MAX_NUM = 100;            // 最大值void print_odd() {while (true) {unique_lock<mutex> lock(mtx);// 等待條件:數字為奇數或超過最大值cv.wait(lock, [] { return (num % 2 == 1) || (num > MAX_NUM); });if (num > MAX_NUM) break;cout << "Odd:  " << num << endl;num++;                      // 遞增到偶數lock.unlock();cv.notify_all();            // 喚醒另一個線程}
}void print_even() {while (true) {unique_lock<mutex> lock(mtx);// 等待條件:數字為偶數或超過最大值cv.wait(lock, [] { return (num % 2 == 0) || (num > MAX_NUM); });if (num > MAX_NUM) break;cout << "Even: " << num << endl;num++;                      // 遞增到奇數lock.unlock();cv.notify_all();            // 喚醒另一個線程}
}int main() {thread t1(print_odd);thread t2(print_even);t1.join();t2.join();return 0;
}

運行結果

????????c++的線程就講到這里,有幫助的話就點點贊吧。

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

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

相關文章

Vscode HTML5新增元素及屬性

一、?HTML5 語義化標簽 HTML5 語義化標簽&#xff08;Semantic Elements&#xff09;是一組 ?具有明確含義的 HTML 元素?&#xff0c;通過標簽名稱直接描述其內容或結構的功能&#xff0c;而非僅作為樣式容器&#xff08;如 <div> 或 <span>&#xff09;。它們旨…

【PostgreSQL教程】PostgreSQL 特別篇之 語言接口Python

博主介紹:?全網粉絲22W+,CSDN博客專家、Java領域優質創作者,掘金/華為云/阿里云/InfoQ等平臺優質作者、專注于Java技術領域? 技術范圍:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大數據、物聯網、機器學習等設計與開發。 感興趣的可…

Three學習入門(四)

9-Three.js 貼圖與材質學習指南 環境準備 <!DOCTYPE html> <html> <head><title>Three.js Texture Demo</title><style> body { margin: 0; } </style> </head> <body><script src"https://cdnjs.cloudflare.…

前端NVM安裝

https://v0.dev/chat/settings 本地啟動環境 1安裝 nvm 2安裝node nvm install v18.19.0 nvm install v20.9.0 nvm use 18 node -v 3安裝 pnpm npm install -g pnpm 或者 npm i -g pnpm 4啟動 代碼 目錄下 執行 pnpm i pnpm run dev 4.1到代碼目錄下 4.2直接cmd…

藍橋杯算法精講:二分查找實戰與變種解析

適合人群&#xff1a;藍橋杯備考生 | 算法競賽入門者 | 二分查找進階學習者 目錄 一、二分查找核心要點 1. 算法思想 2. 適用條件 3. 算法模板 二、藍橋杯真題實戰 例題&#xff1a;分巧克力&#xff08;藍橋杯2017省賽&#xff09; 三、二分查找變種與技巧 1. 查找左邊…

cmd命令查看電腦的CPU、內存、存儲量

目錄 獲取計算機硬件的相關信息的命令分別的功能結果展示結果說明獲取計算機硬件的相關信息的命令 wmic cpu get name wmic memorychip get capacity wmic diskdrive get model,size,mediaType分別的功能 獲取計算機中央處理器(CPU)的名稱 獲取計算機內存(RAM)芯片的容量…

SCI論文閱讀指令(特征工程)

下面是一個SCI論文閱讀特征工程V3.0&#xff0c;把指令輸入大模型中&#xff0c;并上傳PDF論文&#xff0c;就可以幫你快速閱讀論文。 優先推薦kimi&#xff0c;當然DeepSeek、QwQ-32B等大語言模型也可以。測試了一下總結的還不錯&#xff0c;很詳細。 請仔細并深入地閱讀所提…

如何監控 SQL Server

監控 SQL Server 對于維護數據庫性能、確保數據可用性和最大限度地減少停機時間至關重要。隨著企業越來越依賴數據驅動的決策&#xff0c;高效的SQL Server監控策略能顯著提升組織生產力和用戶滿意度。 為什么要監控 SQL Server SQL Server 是許多關鍵應用程序的支柱&#xf…

python腳本處理excel文件

1.對比perl和python 分別嘗試用perl和python處理excel文件&#xff0c;發現perl的比較復雜&#xff0c;比如說read excel就有很多方式 Spreadsheet::Read use Spreadsheet::ParseExcel 不同的method&#xff0c;對應的取sheet的cell方式也不一樣。更復雜的是處理含有中文內…

3、pytest實現參數化

在 pytest 中&#xff0c;參數化&#xff08;parametrization&#xff09;是一種強大的功能&#xff0c;可以讓你用不同的輸入數據重復執行同一個測試函數。這種功能非常有用&#xff0c;可以幫助你顯著減少重復代碼并提高測試覆蓋率。 參數化的主要作用是&#xff1a; 測試多…

Cursor:超強AI變成神器

是一個強大的 AI 編程助手&#xff0c;可以幫助開發者快速地編寫、編輯和討論代碼&#xff0c;支持 Python、Java、C# 等多種編程語言&#xff0c;并且可以與 GitHub、Slack 等平臺集成。 Cursor 是什么&#xff1f; 想象一下&#xff0c;你有一個能把你的創意變成現實的造夢 …

畫秒殺系統流程圖

秒殺系統流程圖 秒殺系統關鍵點 高并發處理: 使用網關&#xff08;如 Nginx&#xff09;進行流量限流&#xff0c;避免過載。分布式鎖或 Redis 原子操作控制并發。 活動狀態檢查: Redis 存儲活動狀態&#xff08;如 seckill:activity:1:status&#xff09;&#xff0c;快速…

【js逆向入門】圖靈爬蟲練習平臺 第九題

地址&#xff1a;aHR0cHM6Ly9zdHUudHVsaW5ncHl0b24uY24vcHJvYmxlbS1kZXRhaWwvOS8 f12進入了debugger&#xff0c;右擊選擇一律不在此處暫停&#xff0c; 點擊繼續執行 查看請求信息 查看載荷&#xff0c;2個加密參數&#xff0c;m和tt 查看啟動器&#xff0c;打上斷點 進來 往…

Vue中的狀態管理器Vuex被Pinia所替代-上手使用指南

Pinia.js 是新一代的狀態管理器&#xff0c;由 Vue.js團隊中成員所開發的&#xff0c;因此也被認為是下一代的 Vuex&#xff0c;即 Vuex5.x&#xff0c;在 Vue3.0 的項目中使用也是備受推崇 Pinia.js 有如下特點&#xff1a; 完整的 typescript 的支持&#xff1b;足夠輕量&…

向量數據庫學習筆記(1) —— 基礎概念

一、 嵌入模型 Embedding Models 嵌入模型是將復雜數據&#xff08;如文本、圖像、音頻等&#xff09;轉換為向量表示的機器學習模型 1. 核心概念 嵌入(Embedding)&#xff1a;將高維、非結構化的數據映射到低維、稠密的向量空間 向量表示&#xff1a;輸出固定長度的數值向量…

[NO-WX179]基于springboot+微信小程序的在線選課系統

[NO-WX179]基于springboot微信小程序的在線選課系統 1、管理員角色&#xff08;web端&#xff09;&#xff1a;2、教師角色&#xff08;web端&#xff09;&#xff1a;3、用戶角色&#xff08;小程序或web端&#xff09;&#xff1a;4、部分運行截圖管理端--教師管理管理端--學…

2025年滲透測試面試題總結-某 長亭(題目+回答)

網絡安全領域各種資源&#xff0c;學習文檔&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各種好玩的項目及好用的工具&#xff0c;歡迎關注。 目錄 長亭 一、Spring SpEL表達式注入漏洞 1. 技術原理 2. 利用條件 3. 攻擊方法 4. 防御策略 二、Jav…

conda環境下解決gitk亂碼模糊

關鍵詞 conda、git、gitk、git gui、模糊、linux、亂碼 現象 操作系統&#xff1a;ubuntu24.04 conda版本&#xff1a;25.1.1 正常的終端里gitk顯示不會模糊 但是在conda創建的python虛擬環境中使用gitk&#xff0c;字體開始變得模糊不清 分析 根據deepseek的原因原因分析…

【C++項目實戰】:基于正倒排索引的Boost搜索引擎(1)

1. 項目的相關背景與目標 針對boost網站沒有搜索導航功能&#xff0c;為boost網站文檔的查找提供搜索功能 站內搜索&#xff1a;搜索的數據更垂直&#xff0c;數據量小 類似于cplusplus.com的搜索 2.搜索引擎的相關宏觀原理 3.技術棧和項目環境 技術棧&#xff1a;C/C&am…

汽車高級駕駛輔助系統應用存儲MRAM

高級駕駛輔助系統和先進的互連航空電子技術等應用要求元件能夠承受惡劣的環境條件&#xff0c;并具有較高的耐用性。閃存雖然在某些條件下性能可靠&#xff0c;但在耐用性方面存在局限性&#xff0c;因此無法滿足這些嚴格的要求。 在實時傳感器數據處理或高可靠性通信等對時間…