c++多線程(1)------創建和管理線程td::thread

  • 操作系統:ubuntu22.04
  • IDE:Visual Studio Code
  • 編程語言:C++11

算法描述

std::thread 是 C++11 標準庫中用于創建和管理線程的核心類,定義在 頭文件中。它使得多線程編程變得簡單、類型安全且跨平臺。

一、std::thread 簡介

std::thread 是一個類,代表一個執行線程。你可以用它來啟動一個函數(普通函數、lambda、函數對象、成員函數等)在新的線程中運行。
🔧 所需頭文件:

#include <thread>

📦 常用成員函數:

函數說明
join()等待線程執行完畢(阻塞主線程)
detach()分離線程,讓其在后臺獨立運行
get_id()獲取線程的唯一 ID
joinable()判斷線程是否可以 join 或 detach
swap()交換兩個 thread 對象
native_handle()獲取底層平臺的原生線程句柄(如 pthread_t)

二、創建線程的多種方式(附示例)

  1. 使用普通函數
#include <iostream>
#include <thread>
#include <chrono>void hello() 
{std::this_thread::sleep_for(std::chrono::milliseconds(100));std::cout << "Hello from thread " << std::this_thread::get_id() << std::endl;
}int main()
{std::thread t(hello);  // 啟動線程執行 hello 函數std::cout << "Main thread ID: " << std::this_thread::get_id() << std::endl;t.join();  // 等待線程結束std::cout << "Thread joined." << std::endl;return 0;
}

輸出示例:

Main thread ID: 1
Hello from thread 2
Thread joined.
  1. 使用帶參數的函數
void print_message(const std::string& msg, int n) 
{for (int i = 0; i < n; ++i) {std::cout << msg << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(50));}
}int main()
{std::thread t(print_message, "Hello from thread!", 3);std::cout << "Main thread is running..." << std::endl;t.join();std::cout << "Thread finished." << std::endl;return 0;
}
?? 注意:參數是值傳遞的。如果要傳引用,必須用 std::ref。

? 正確傳遞引用:

void increment(int& x)
{++x;
}int main() 
{int a = 0;std::thread t(increment, std::ref(a));  // 使用 std::ref 傳引用t.join();std::cout << "a = " << a << std::endl;  // 輸出: a = 1return 0;
}

? 3. 使用 Lambda 表達式

int main()
{int local = 10;std::thread t([local](){  // 捕獲 local 的副本std::cout << "Lambda: local = " << local << std::endl;std::this_thread::sleep_for(std::chrono::seconds(1));});t.join();return 0;
}
提示:如果要修改捕獲的變量,使用 mutable 或傳引用:
std::thread t([&local]() mutable 
{local += 5;std::cout << "Modified: " << local << std::endl;
});

? 4. 使用函數對象(仿函數)

struct Task 
{void operator()() const{std::cout << "Task executed in thread " << std::this_thread::get_id() << std::endl;}
};int main() 
{std::thread t(Task{});t.join();return 0;
}

? 5. 使用類的成員函數

class Worker 
{
public:void work(int id){std::cout << "Worker " << id << " working in thread " << std::this_thread::get_id() << std::endl;}
};int main() 
{Worker w;std::thread t(&Worker::work, &w, 42);  // &w 是對象指針,42 是參數t.join();return 0;
}

🔍 解釋:&Worker::work 是成員函數指針,&w 是對象地址,42 是參數。

三、join() vs detach()

? 每個 std::thread 對象在析構前必須被 join 或 detach,否則程序會 std::terminate()。
? join():等待線程結束

std::thread t(some_function);
t.join();  // 主線程阻塞,直到 t 結束
// 此時 t 不再可 join,t.joinable() 返回 false

? detach():分離線程

std::thread t(some_function);
t.detach();  // 線程在后臺運行,不再與 thread 對象關聯
// 不能再 join,線程生命周期由系統管理
?? 分離線程的風險:如果主線程結束,整個程序終止,分離線程也會被強制終止。

🧪 四、檢查線程狀態:joinable()

std::thread t(some_function);if (t.joinable()) 
{t.join();  // 安全調用
}
常用于異常安全代碼中,確保線程被正確處理。

🧰 五、線程 ID 與當前線程操作

#include <iostream>
#include <thread>void show_id() 
{std::cout << "This thread ID: " << std::this_thread::get_id() << std::endl;
}int main() 
{std::thread t(show_id);std::cout << "Main thread ID: " << std::this_thread::get_id() << std::endl;t.join();// 讓出 CPU 時間片std::this_thread::yield();// 休眠 500 毫秒std::this_thread::sleep_for(std::chrono::milliseconds(500));return 0;
}

🧱 六、線程安全與共享數據(簡單示例)

#include <iostream>
#include <thread>
#include <mutex>int counter = 0;
std::mutex mtx;void increment() 
{for (int i = 0; i < 100000; ++i) {std::lock_guard<std::mutex> lock(mtx);++counter;}
}int main() 
{std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();std::cout << "Final counter: " << counter << std::endl;  // 應為 200000return 0;
}
🔐 使用 std::mutex 和 std::lock_guard 保護共享變量 counter。

🚫 七、常見錯誤與注意事項

? 錯誤1:未調用 join 或 detach

int main()
{std::thread t([]{ std::cout << "Hello"; });return 0;  // t 析構時未 join/detach → 調用 std::terminate()
}

? 正確做法:

std::thread t(...);
// ...
t.join();  // 或 t.detach();

? 錯誤2:傳遞指針或引用時對象已銷毀

std::thread t(increment, std::ref(local_var));
// 如果 local_var 是局部變量且線程未結束,可能訪問已銷毀內存
? 建議:確保線程使用的數據生命周期長于線程本身。

? 八、完整示例:多線程并行計算

#include <iostream>
#include <vector>
#include <thread>
#include <numeric>void accumulate(const std::vector<int>& vec, int start, int end, int& result){result = std::accumulate(vec.begin() + start, vec.begin() + end, 0);
}int main() 
{std::vector<int> data(100000, 1);  // 10萬個1int sum1 = 0, sum2 = 0;std::thread t1(accumulate, std::ref(data), 0, 50000, std::ref(sum1));std::thread t2(accumulate, std::ref(data), 50000, 100000, std::ref(sum2));t1.join();t2.join();std::cout << "Total sum: " << sum1 + sum2 << std::endl;  // 100000return 0;
}

總結:std::thread 核心要點

要點說明
? 啟動線程std::thread t(func, args…)
? 等待結束t.join()
? 后臺運行t.detach()
? 安全檢查t.joinable()
? 線程IDt.get_id() 或 std::this_thread::get_id()
? 傳引用使用 std::ref()
? 異常安全在異常路徑中也要 join/detach

掌握 std::thread 是學習 C++ 多線程的第一步。結合 mutex、condition_variable 和 future,你就能構建出高效、安全的并發程序。建議多寫小例子練習傳參、生命周期管理、同步等關鍵點。

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

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

相關文章

Flutter環境搭建全攻略之-windows環境搭建

一&#xff0c;Flutter 官網&#xff1a;https://flutter.dev Flutter Packages官網&#xff1a;https://pub.dev 二&#xff0c;Windows 上面搭建Flutter Android運行環境 對應軟件可以聯系客服&#xff0c;或者網盤里面下載 1&#xff0c;Flutter Android環境搭建&#xff1a…

《Docker 零基礎入門到實戰:容器化部署如此簡單,運維效率直接拉滿》

相信你對封面圖上的「Docker 鯨魚」圖標并不陌生 —— 它正是解決「開發環境能跑&#xff0c;生產環境崩了」的容器化神器&#xff01;Docker 通過打包應用與依賴到輕量容器&#xff0c;實現了「一次構建&#xff0c;到處運行」&#xff0c;徹底消除環境不一致的痛點。本文從 D…

Spring Security 深度學習(六): RESTful API 安全與 JWT

目錄 1. 引言&#xff1a;無狀態認證的崛起2. JWT (JSON Web Token) 核心概念2.1 什么是JWT&#xff1f;2.2 JWT的組成&#xff1a;Header, Payload, Signature2.3 JWT的工作原理2.4 JWT的優缺點與適用場景 3. Spring Security中的JWT集成策略3.1 禁用Session管理與CSRF防護3.2…

無名信號量

include <myhead.h> oid *task( void *file_size)int file_size1*(int*)file_size;//打開源文件int fdopen("./hello",O_RDONLY);if(fd-1){perror("open error\n");return NULL;}//打開目標文件int fd1open("./world",O_WRONLY);if(fd1-1)…

免費CRM系統與Excel客戶管理的區別

很多中小企業在客戶管理初期&#xff0c;會選擇使用Excel表格進行客戶數據的整理與維護。但隨著業務規模擴大&#xff0c;客戶信息日益復雜&#xff0c;Excel逐漸暴露出諸多局限性。此時&#xff0c;免費CRM系統應運而生&#xff0c;成為企業客戶管理升級的重要選擇。本文將深入…

linux Nginx服務配置介紹,和配置流程

1、Nginx 配置介紹認識Nginx服務的主配置文件 nginx.confnginx的配置文件一般在 /usr/local/nginx/conf/下&#xff0c;然后直接vim nginx.com 即可編輯1.1 全局配置介紹全局配置位于主配置文件最頂部&#xff0c;作用于整個Nginx服務進程&#xff0c;影響服務的資源分配、運行…

文字識別接口-文字識別技術-ocr api

文字識別接口&#xff0c;顧名思義&#xff0c;就是一種將圖像文字或手寫文字轉換為可編輯文本的技術。文字識別接口&#xff0c;基于深度學習算法與自主ocr核心實現多種場景字符的高精度識別與結構化信息提取&#xff0c;現已被廣泛應用于銀行、醫療、財會、教育等多個領域。隨…

DeepSeek R1大模型微調實戰-llama-factory的模型下載與訓練

文章目錄概要1.下載模型2.llama factory 訓練模型2.1 模型微調2.2 模型評估2.3 模型對話2.4 導出模型3.硬件選擇概要 LLaMA Factory 是一個簡單易用且高效的大型語言模型訓練與微調平臺。通過它&#xff0c;用戶可以在無需編寫任何代碼的前提下&#xff0c;在本地完成上百種預…

C++ map和set

C參考文獻&#xff1a;cplusplus.com - The C Resources Network 目錄 一、序列式容器和關聯式容器 二、set系列 &#xff08;1&#xff09;set類的介紹 &#xff08;2&#xff09;set的構造和迭代器 &#xff08;3&#xff09;set的接口 1.insert?編輯 2.find和erase 3…

頭一次見問這么多kafka的問題

分享一篇粉絲朋友整理的面經&#xff0c;第一次遇見問那么多kafka的問題&#xff0c;看看他是怎么回答的。 先來看看 職位描述&#xff1a; 崗位職責&#xff1a; 負責基于 Go 的后端服務的設計、開發和維護&#xff1b;參與系統架構設計&#xff0c;確保系統的高可用性、高性能…

自底向上了解CPU的運算

文章目錄 引言 CPU如何實現邏輯運算 NMOS和PMOS 基于MOS管組合下的邏輯門運算 邏輯運算下運算的實現 ALU的誕生 CPU的誕生 關于二進制運算的研究 十進制轉二進制基礎換算 為什么負數要使用補碼進行表示 為什么反碼就能解決正負數相加問題,我們還需要用補碼來表示負數呢? 小數…

apache poi與Office Open XML關系

以下內容來自AI https://ecma-international.org/publications-and-standards/standards/ecma-376/ 官方規范 https://poi.apache.org/components/oxml4j/index.html java中針對Office Open XML的實現 Apache poi中各個組件 https://poi.apache.org/components/index.html …

S32K328上芯片內部RTC的使用和喚醒配置

1&#xff1a;RTC介紹 1.1 RTC基礎功能介紹 參考《S32K3xx Reference Manual》&#xff0c;S32K328芯片內部自帶RTC功能&#xff0c;并且支持從低功耗狀態下喚醒設備&#xff1b;1.2 RTC電源介紹 由以下三張圖可知 1&#xff1a;RTC由V11供電&#xff0c;V11依賴外部V15供電&am…

【Python】數據可視化之分類圖

目錄 條形圖 箱形圖 散點圖 分簇散點圖 小提琴 分簇小提琴 條形圖 條形圖是一種直觀的圖表形式&#xff0c;它通過不同長度的矩形條&#xff08;即“條形”&#xff09;來展示數值變量的中心趨勢估計值&#xff0c;其中每個矩形的高度直接對應于該組數據的某個中心量度&…

RabbitMQ模型詳解與常見問題

項目demo地址&#xff1a;https://github.com/tian-qingzhao/rabbitmq-demo 一、RabbitMQ組件概念 1.1 Server&#xff1a;接收客戶端的連接&#xff0c;實現AMQP實體服務。 1.2 Connection&#xff1a;連接 應用程序與Server的網絡連接&#xff0c;TCP連接。 1.3 Channel&…

網絡:相比于HTTP,HTTPS協議到底安全在哪?

網絡&#xff1a;相比于HTTP&#xff0c;HTTPS協議到底安全在哪&#xff1f; 我們知道HTTPS也是一種應用層協議&#xff0c;它在HTTP的基礎上有一層加密&#xff0c;因為HTTP的數據傳輸都是以明文方式傳輸的&#xff0c;所以加密主要是為了防止數據在傳輸的時候被篡改 今天我…

AI 基礎設施新范式,百度百舸 5.0 技術深度解析

本文整理自 2025 年 8 月 29 日百度云智大會 —— AI 算力平臺專題論壇&#xff0c;百度智能云 AI 計算首席科學家王雁鵬的同名主題演講。大家下午好&#xff01;昨天在主論壇&#xff0c;我們正式發布了百度百舸 AI 計算平臺 5.0&#xff0c;并展示了多項亮眼的性能數據。今天…

IO進程線程;多線程;線程互斥同步;互斥鎖;無名信號量;條件變量;0905

思維導圖多線程打印ABC運用無名面量 實現進程同步#include<myhead.h> //定義 無名信號量 sem_t sem1; sem_t sem2; sem_t sem3; //線程1 void* task1(void *arg) {while(1){sem_wait(&sem1);printf("A");fflush(stdout);sleep(1);sem_post(&sem2);} } …

固高 GTS-800 運動控制卡完全使用指南:從硬件部署到高階應用

固高 GTS-800 系列運動控制卡作為中端工業控制領域的標桿產品,以其 8-16 軸同步控制能力、豐富的插補功能和穩定的性能,廣泛應用于激光加工、PCB 制造、精密裝配等自動化設備中。本文將系統講解 GTS-800 的硬件架構、開發環境搭建、核心功能實現及工程實踐技巧,幫助工程師快…

STM32F103_Bootloader程序開發15 - 從Keil到vscode + EIDE + GCC的遷移實踐

導言 STM32 - Embedded IDE - GCC - 如何在工程中生成.bin格式固件 STM32 - Embedded IDE - GCC - 使用 GCC 鏈接腳本限制 Flash 區域 STM32 - Embedded IDE - GCC - 如何在工程中定義一段 NoInit RAM 內存 STM32 - Embedded IDE - GCC - 如何將編譯得到的.bin固件添加CRC32校驗…