第16天:C++多線程完全指南 - 從基礎到現代并發編程

第16天:C++多線程完全指南 - 從基礎到現代并發編程

一、多線程基礎概念

1. 線程創建與管理(C++11)

#include <iostream>
#include <thread>void hello() {std::cout << "Hello from thread " << std::this_thread::get_id() << "\n";
}int main() {std::thread t1(hello);std::thread t2([](){std::cout << "Lambda thread running\n";});t1.join();  // 等待線程完成t2.join();// 輸出可能交錯:// Hello from thread 140245230233344// Lambda thread running
}

2. 并發與并行區別

  • 并發:交替處理多個任務(單核)
  • 并行:同時處理多個任務(多核)
// 查看硬件支持線程數
unsigned int n = std::thread::hardware_concurrency();
std::cout << n << " concurrent threads supported\n";

二、線程同步核心機制

1. 互斥鎖(mutex)與RAII

#include <mutex>std::mutex mtx;
int shared_data = 0;void safe_increment() {std::lock_guard<std::mutex> lock(mtx); // 自動釋放鎖++shared_data;  // 臨界區操作
}int main() {std::thread threads[10];for (auto& t : threads) {t = std::thread(safe_increment);}for (auto& t : threads) {t.join();}std::cout << "Final value: " << shared_data; // 正確輸出10
}

2. 條件變量(生產者-消費者模式)

#include <queue>
#include <condition_variable>std::mutex mtx;
std::condition_variable cv;
std::queue<int> data_queue;void producer() {for (int i=0; i<5; ++i) {{std::lock_guard<std::mutex> lock(mtx);data_queue.push(i);}cv.notify_one();  // 通知消費者std::this_thread::sleep_for(std::chrono::milliseconds(100));}
}void consumer() {while(true) {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, []{ return !data_queue.empty(); });int data = data_queue.front();data_queue.pop();lock.unlock();std::cout << "Consumed: " << data << "\n";if(data == 4) break;}
}

三、現代C++并發特性

1. 異步任務(std::async)

#include <future>int compute(int x) {return x * x;
}int main() {auto future = std::async(std::launch::async, compute, 12);std::cout << "Result: " << future.get();  // 輸出144
}

2. 原子操作(std::atomic)

#include <atomic>std::atomic<int> counter(0);  // 無需鎖的線程安全計數器void increment() {for (int i=0; i<100000; ++i) {++counter;  // 原子操作}
}// 測試:兩個線程同時遞增
// 最終結果正確為200000

四、線程安全設計模式

1. 線程局部存儲(thread_local)

thread_local int tls_var = 0;  // 每個線程獨立副本void thread_func() {++tls_var;std::cout << "Thread " << std::this_thread::get_id() << ": " << tls_var << "\n";
}// 每個線程輸出自己的遞增結果

2. 線程池實現(C++17)

#include <vector>
#include <functional>
#include <queue>class ThreadPool {std::vector<std::thread> workers;std::queue<std::function<void()>> tasks;std::mutex queue_mutex;std::condition_variable condition;bool stop = false;public:ThreadPool(size_t threads) {for(size_t i=0; i<threads; ++i) {workers.emplace_back([this]{while(true) {std::function<void()> task;{std::unique_lock<std::mutex> lock(queue_mutex);condition.wait(lock, [this]{ return stop || !tasks.empty(); });if(stop && tasks.empty()) return;task = std::move(tasks.front());tasks.pop();}task();}});}}template<class F>void enqueue(F&& f) {{std::lock_guard<std::mutex> lock(queue_mutex);tasks.emplace(std::forward<F>(f));}condition.notify_one();}~ThreadPool() {{std::lock_guard<std::mutex> lock(queue_mutex);stop = true;}condition.notify_all();for(auto& worker : workers)worker.join();}
};

五、并發編程陷阱與調試

1. 死鎖檢測示例

std::mutex m1, m2;void thread_A() {std::lock_guard<std::mutex> lock1(m1);std::this_thread::sleep_for(std::chrono::milliseconds(100));std::lock_guard<std::mutex> lock2(m2); // 可能死鎖點
}void thread_B() {std::lock_guard<std::mutex> lock2(m2);std::this_thread::sleep_for(std::chrono::milliseconds(100));std::lock_guard<std::mutex> lock1(m1); // 可能死鎖點
}// 解決方案:使用std::lock同時鎖定多個互斥量
void safe_lock() {std::lock(m1, m2);std::lock_guard<std::mutex> lock1(m1, std::adopt_lock);std::lock_guard<std::mutex> lock2(m2, std::adopt_lock);
}

六、現代C++并發增強

1. C++20信號量(semaphore)

#include <semaphore>std::counting_semaphore<5> sem(3);  // 允許3個同時訪問void limited_thread() {sem.acquire();// 訪問受限資源sem.release();
}

2. 屏障(C++20 barrier)

std::barrier sync_point(3);  // 等待3個線程到達void worker() {// Phase 1sync_point.arrive_and_wait();// Phase 2(所有線程完成Phase1后繼續)
}

七、常見問題解答

Q:如何檢測數據競爭?

  • 使用ThreadSanitizer編譯:
g++ -fsanitize=thread -g -O1 program.cpp
  • 示例輸出:
WARNING: ThreadSanitizer: data race

Q:std::mutex和std::shared_mutex區別?

  • std::mutex:獨占鎖
  • std::shared_mutex:讀寫鎖(C++17)
std::shared_mutex smtx;// 寫操作使用獨占鎖
{std::unique_lock lock(smtx);data = new_value;
}// 讀操作使用共享鎖
{std::shared_lock lock(smtx);read_data = data;
}

八、今日總結

? 核心掌握:

  • 🧵 線程生命周期管理(創建、等待、分離)
  • 🔒 同步原語使用場景(mutex/atomic/condition_variable)
  • 🚧 典型并發問題檢測與預防(死鎖、數據競爭)

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

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

相關文章

Pwntools 的詳細介紹、安裝指南、配置說明

Pwntools&#xff1a;Python 開源安全工具箱 一、Pwntools 簡介 Pwntools 是一個由 Security researcher 開發的 高效 Python 工具庫&#xff0c;專為密碼學研究、漏洞利用、協議分析和逆向工程設計。它集成了數百個底層工具的功能&#xff0c;提供統一的 Python API 接口&am…

ES的簡單講解

功能 &#xff1a; 文檔存儲 與 文檔搜索 特點&#xff1a;比如有一個文檔名 “你好” 可以用‘你‘&#xff0c;好&#xff0c;你好都可以搜索到這個文檔 ES核心概念 類似于數據庫中表的概念&#xff0c;在表的概念下又對數據集合進行了細分 ? ES_Client查詢接口 cpr::R…

leetcode_字典樹 139. 單詞拆分

139. 單詞拆分 給你一個字符串 s 和一個字符串列表 wordDict 作為字典。如果可以利用字典中出現的一個或多個單詞拼接出 s 則返回 true。 注意&#xff1a;不要求字典中出現的單詞全部都使用&#xff0c;并且字典中的單詞可以重復使用。 思路: 定義狀態&#xff1a; 設dp[i]表…

寶塔安裝向量數據庫-Milvus

注&#xff1a;寶塔需要安裝好docker容器組件&#xff01; 1、純血寶塔安裝 1.1 在線上鏡像中&#xff0c;拉取milvus鏡像&#xff0c;創建milvus容器 1.2 安裝milvus管理工具ATTU&#xff1b;同樣方式拉取線上鏡像創建attu容器 2、自定義安裝 2.1修改配置 {"registry-…

【K8S】Kubernetes 基本架構、節點類型及運行流程詳解(附架構圖及流程圖)

Kubernetes 架構 k8s 集群 多個 master node 多個 work nodeMaster 節點&#xff08;主節點&#xff09;&#xff1a;負責集群的管理任務&#xff0c;包括調度容器、維護集群狀態、監控集群、管理服務發現等。Worker 節點&#xff08;工作節點&#xff09;&#xff1a;實際運…

數據庫MySQL,在終端輸入后,提示不是內部命令等

【解決問題】mysql提示不是內部或外部命令&#xff0c;也不是可運行的程序 一般這種問題是因為沒有在系統變量里面添加MySQL的可執行路徑 以下是添加可執行路徑的方法&#xff1a; 第一步&#xff1a;winR輸入services.msc 然后找到MySQL&#xff0c;右擊屬性并復制MySQL的可執…

Python 中的線程模塊

Python 中的線程模塊 Python 中的線程模塊 Python 中的線程模塊 thread 模塊是一個標準模塊&#xff0c;提供了簡單易用的方法為程序構建多線程。在幕后&#xff0c;該模塊使用較低級的 _thread 模塊&#xff0c;在 Python 早期版本中&#xff0c;該模塊是多線程的流行選擇。 …

PhotoShop學習01

了解Photoshop 這里省略了Photoshop的軟件安裝&#xff0c;請自行查找資源下載。 1.打開圖片 下圖為啟動photoshop后出現的界面&#xff0c;我們可以通過創建新文件或打開已有文件來啟用photoshop的工作界面。 可以通過左邊的按鈕進行新文件的創建或打開已有文件。 也可以點…

Python大戰Java:AI時代的編程語言‘復仇者聯盟‘能否換C位?

背景 當Java程序員在咖啡機前念叨’Python憑什么搶我飯碗’時&#xff0c;AI實驗室里的Python工程師正用5行代碼召喚出神經網絡——這場編程語言的’權力的游戲’&#xff0c;勝負可能比你想象的更魔幻&#xff01;" 一、茶水間里的戰爭&#xff1a;Java和Python的相愛相…

GitCode 助力 python-office:開啟 Python 自動化辦公新生態

項目倉庫&#xff1a;https://gitcode.com/CoderWanFeng1/python-office 源于需求洞察&#xff0c;打造 Python 辦公神器 項目作者程序員晚楓在運營擁有 14w 粉絲的 B 站賬號 “Python 自動化辦公社區” 時&#xff0c;敏銳察覺到非程序員群體對 Python 學習的強烈需求。在數字…

javaweb + AI day03

一、web基礎 二、分層解耦 注意&#xff1a;bean的名字默認是類名的首字母小寫&#xff01;&#xff01;&#xff01; 三、Mysql count不參與null值統計 四、JDBC 五、MyBatis 數據庫連接池

運行程序時出現加載配置文件時出錯,對路徑****的訪問被拒絕

問題&#xff1a;最近給客戶用c#語言編寫進銷存項目&#xff0c;在用vs2022自帶的打包工具Microsoft visual studio installer projects 打包生成了安裝文件&#xff0c;順利安裝后&#xff0c;點擊桌面快捷方式后出現如下錯誤 經過查詢相關資料發現是桌面快捷方式的權限問題&a…

基于C#的CANoe CLR Adapter開發指南

一、引言 CANoe 是一款廣泛應用于汽車電子開發和測試的工具&#xff0c;它支持多種編程接口&#xff0c;方便開發者進行自定義擴展。CANoe CLR Adapter 允許我們使用 C# 語言與 CANoe 進行交互&#xff0c;充分利用 C# 的強大功能和豐富的類庫。本文將詳細介紹如何基于 C# 進行…

conda怎么遷移之前下載的環境包,把python從3.9升級到3.10

克隆舊環境&#xff08;保留舊環境作為備份&#xff09; conda create -n cloned_env --clone old_env 在克隆環境中直接升級 Python conda activate cloned_env conda install python3.10 升級 Python 后出現 所有包導入失敗 的問題&#xff0c;通常是因為依賴包與新 Pyth…

一文掌握 Scrapy 框架的詳細使用,包括實戰案例

更多內容請見: 爬蟲和逆向教程-專欄介紹和目錄 文章目錄 1. Scrapy 簡介2. Scrapy 的核心組件3. 安裝 Scrapy4. 創建 Scrapy 項目4.1 創建項目4.2 創建 Spider5. 編寫 Spider5.1 定義 Item5.2 編寫 Spider 邏輯6. 運行 Scrapy 爬蟲6.1 運行爬蟲6.2 保存爬取數據7. Scrapy 的高…

筆試-查找最長公共字符串

應用 以字符串形式給定兩行代碼&#xff0c;1<長度<100&#xff0c;由字母、數字、空格組成。請找出最長公共子字符串&#xff0c;如果不存在返回空字符串。 實現 str1 input("請輸入字符串1&#xff1a;") str2 input("請輸入字符串2&#xff1a;&q…

【三維分割】LangSplat: 3D Language Gaussian Splatting(CVPR 2024 highlight)

論文&#xff1a;https://arxiv.org/pdf/2312.16084 代碼&#xff1a;https://github.com/minghanqin/LangSplat 文章目錄 一、3D language field二、回顧 Language Fields的挑戰三、使用SAM學習層次結構語義四、Language Fields 的 3DGS五、開放詞匯查詢&#xff08;Open-voca…

haclon固定相機位標定

什么是標定&#xff1f; 工業應用中相機拍到一個mark點的坐標為C1&#xff08;Cx,Cy&#xff09;&#xff0c;C1點對應的龍門架/機械手等執行端對應的坐標是多少&#xff1f; 標定就是解決這個問題&#xff0c;如相機拍到一個點坐標C1&#xff08;Cx,Cy&#xff09;&#xff0c…

# 代碼寫作風格:優雅編程的藝術

在編程的世界里&#xff0c;代碼不僅僅是實現功能的工具&#xff0c;更是一種表達思想和藝術的方式。良好的代碼寫作風格不僅能夠提高代碼的可讀性和可維護性&#xff0c;還能讓其他開發者更容易理解和協作。本文將探討代碼寫作風格的重要性以及如何培養優雅的編程風格。 ## 一…

【通俗講解電子電路】——從零開始理解生活中的電路(二)

電路分析&#xff1a;看懂簡單的“電路圖” ——從“路線圖”到“工具箱”&#xff0c;掌握電路的底層邏輯 1. 歐姆定律&#xff1a;電的“交通規則” 公式解析&#xff1a;V I R 電壓&#xff08;V&#xff09;&#xff1a;推動電流的動力&#xff08;如電池電壓&#xff…