C++常用多線程模式

文章目錄

      • 1. Fork - Join模式
      • 2. Producer - Consumer模式
      • 3. Readers - Writers模式
      • 4. Work Thread模式
      • 5. Actor模式
      • 6、 Pipeline模式概述
      • 應用場景
      • C++實現示例
      • 代碼解釋

1. Fork - Join模式

  • 原理:將一個大任務分解為多個子任務,這些子任務在不同的線程中并行執行,當所有子任務完成后,再將它們的結果合并得到最終結果。
  • 優點:充分利用多核處理器的并行能力,提高計算效率;任務分解和結果合并的過程清晰,便于理解和實現分治算法等。
  • 缺點:需要考慮子任務的劃分合理性以及線程間的同步問題,以確保結果的正確性。
  • 適用場景:適用于能有效分解為多個獨立子任務的計算密集型任務,如大規模數據處理、科學計算中的矩陣運算等。
#include <iostream>
#include <vector>
#include <thread>
#include <numeric>// 計算數組某區間的和
void sum_subarray(const std::vector<int>& arr, int start, int end, int& result) {result = std::accumulate(arr.begin() + start, arr.begin() + end, 0);
}int main() {std::vector<int> arr(1000);std::iota(arr.begin(), arr.end(), 1);int mid = arr.size() / 2;int left_sum = 0, right_sum = 0;// Fork: 創建兩個線程分別計算左右子數組的和std::thread left_thread(sum_subarray, std::ref(arr), 0, mid, std::ref(left_sum));std::thread right_thread(sum_subarray, std::ref(arr), mid, arr.size(), std::ref(right_sum));// Join: 等待兩個線程完成left_thread.join();right_thread.join();int total_sum = left_sum + right_sum;std::cout << "Total sum: " << total_sum << std::endl;return 0;
}

2. Producer - Consumer模式

  • 原理:生產者線程負責生產數據并將其放入緩沖區,消費者線程從緩沖區取出數據進行處理。通過緩沖區實現生產者和消費者的解耦,使它們可以以不同的速度運行。
  • 優點:提高了程序的并發度和整體性能,生產者和消費者可以獨立優化和擴展,代碼可讀性和維護性較好。
  • 缺點:需要合理設計緩沖區大小和同步機制,避免緩沖區溢出或不足,同時要處理好生產者和消費者之間的同步與互斥問題。
  • 適用場景:廣泛應用于各種數據處理場景,如文件讀取與處理、網絡數據的接收與解析、消息隊列系統等。
#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>std::queue<int> task_queue;
std::mutex mtx;
std::condition_variable cv;
bool is_running = true;// 生產者函數
void producer() {for (int i = 0; i < 10; ++i) {std::this_thread::sleep_for(std::chrono::milliseconds(100));{std::unique_lock<std::mutex> lock(mtx);task_queue.push(i);std::cout << "Produced: " << i << std::endl;}cv.notify_one();}{std::unique_lock<std::mutex> lock(mtx);is_running = false;}cv.notify_all();
}// 消費者函數
void consumer() {while (true) {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [] { return!task_queue.empty() ||!is_running; });if (task_queue.empty() &&!is_running) {break;}int task = task_queue.front();task_queue.pop();std::cout << "Consumed: " << task << std::endl;}
}int main() {std::thread producer_thread(producer);std::thread consumer_thread(consumer);producer_thread.join();consumer_thread.join();return 0;
}

3. Readers - Writers模式

  • 原理:允許多個讀者線程同時訪問共享資源,但當有寫者線程訪問時,所有讀者和其他寫者都需等待。寫者線程具有更高的優先級,以確保數據的一致性。
  • 優點:能有效提高對共享資源的訪問效率,在有大量讀操作和少量寫操作的情況下,能充分利用多核處理器的并行性。
  • 缺點:實現較為復雜,需要精細地控制讀寫線程的同步與互斥,以避免數據不一致和死鎖等問題。
  • 適用場景:常用于數據庫系統、文件系統等需要頻繁讀寫共享數據的場景,其中讀操作遠遠多于寫操作。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>std::mutex rw_mutex;
std::condition_variable rw_cv;
int readers = 0;
bool writer_active = false;// 讀者函數
void reader(int id) {{std::unique_lock<std::mutex> lock(rw_mutex);rw_cv.wait(lock, [] { return!writer_active; });++readers;}std::cout << "Reader " << id << " is reading." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(100));{std::unique_lock<std::mutex> lock(rw_mutex);--readers;if (readers == 0) {rw_cv.notify_one();}}
}// 寫者函數
void writer(int id) {{std::unique_lock<std::mutex> lock(rw_mutex);rw_cv.wait(lock, [] { return!writer_active && readers == 0; });writer_active = true;}std::cout << "Writer " << id << " is writing." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(100));{std::unique_lock<std::mutex> lock(rw_mutex);writer_active = false;rw_cv.notify_all();}
}int main() {std::thread r1(reader, 1);std::thread r2(reader, 2);std::thread w1(writer, 1);std::thread r3(reader, 3);r1.join();r2.join();w1.join();r3.join();return 0;
}

4. Work Thread模式

  • 原理:有一個任務隊列,多個工作線程從隊列中獲取任務并執行。任務隊列可以是優先級隊列或普通隊列,工作線程根據一定的規則從隊列中取出任務進行處理。
  • 優點:實現相對簡單,易于擴展工作線程的數量來應對不同的負載需求,能有效利用線程資源,避免線程的頻繁創建和銷毀。
  • 缺點:任務隊列的管理和線程的調度需要一定的開銷,可能會出現任務饑餓現象,即某些低優先級任務長時間得不到執行。
  • 適用場景:適用于處理大量異步任務的場景,如網絡服務器中的請求處理、分布式系統中的任務調度等。
#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <vector>std::queue<std::function<void()>> work_queue;
std::mutex queue_mutex;
std::condition_variable queue_cv;
bool is_working = true;// 工作線程函數
void worker() {while (true) {std::function<void()> task;{std::unique_lock<std::mutex> lock(queue_mutex);queue_cv.wait(lock, [] { return!work_queue.empty() ||!is_working; });if (work_queue.empty() &&!is_working) {break;}task = std::move(work_queue.front());work_queue.pop();}task();}
}int main() {std::vector<std::thread> workers;for (int i = 0; i < 3; ++i) {workers.emplace_back(worker);}// 添加任務到隊列{std::unique_lock<std::mutex> lock(queue_mutex);for (int i = 0; i < 5; ++i) {work_queue.emplace([i] {std::cout << "Task " << i << " is being executed." << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(100));});}}queue_cv.notify_all();// 等待所有任務完成{std::unique_lock<std::mutex> lock(queue_mutex);is_working = false;}queue_cv.notify_all();for (auto& t : workers) {t.join();}return 0;
}

5. Actor模式

  • 原理:將整個處理過程分為多個階段,每個階段由一個或多個Actor(參與者)負責。數據在這些Actor之間像流水線一樣依次傳遞,每個Actor處理完數據后將其傳遞給下一個Actor,直到最終處理完成。
  • 優點:提高了系統的吞吐量和響應性,各個階段可以并行執行,而且易于維護和擴展,每個Actor可以獨立開發和測試。
  • 缺點:需要精心設計流水線的各個階段和數據傳遞方式,以確保數據的正確流轉和系統的穩定性。
  • 適用場景:適用于處理流程較為復雜且可以明確劃分為多個階段的任務,如視頻編碼解碼、圖像處理流水線、網絡數據包的處理等。
#include <iostream>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>// 第一個階段 Actor
class FirstActor {
public:std::queue<int> input_queue;std::mutex mtx;std::condition_variable cv;bool is_finished = false;void run() {for (int i = 0; i < 5; ++i) {std::this_thread::sleep_for(std::chrono::milliseconds(100));{std::unique_lock<std::mutex> lock(mtx);input_queue.push(i);}cv.notify_one();}{std::unique_lock<std::mutex> lock(mtx);is_finished = true;}cv.notify_all();}
};// 第二個階段 Actor
class SecondActor {
public:FirstActor& first_actor;std::queue<int> output_queue;std::mutex mtx;std::condition_variable cv;bool is_finished = false;SecondActor(FirstActor& fa) : first_actor(fa) {}void run() {while (true) {int data;{std::unique_lock<std::mutex> lock(first_actor.mtx);first_actor.cv.wait(lock, [this] { return!first_actor.input_queue.empty() || first_actor.is_finished; });if (first_actor.input_queue.empty() && first_actor.is_finished) {break;}data = first_actor.input_queue.front();first_actor.input_queue.pop();}data *= 2;{std::unique_lock<std::mutex> lock(mtx);output_queue.push(data);}cv.notify_one();}{std::unique_lock<std::mutex> lock(mtx);is_finished = true;}cv.notify_all();}
};// 第三個階段 Actor
class ThirdActor {
public:SecondActor& second_actor;ThirdActor(SecondActor& sa) : second_actor(sa) {}void run() {while (true) {int data;{std::unique_lock<std::mutex> lock(second_actor.mtx);second_actor.cv.wait(lock, [this] { return!second_actor.output_queue.empty() || second_actor.is_finished; });if (second_actor.output_queue.empty() && second_actor.is_finished) {break;}data = second_actor.output_queue.front();second_actor.output_queue.pop();}std::cout << "Final result: " << data << std::endl;}}
};int main() {FirstActor first_actor;SecondActor second_actor(first_actor);ThirdActor third_actor(second_actor);std::thread t1(&FirstActor::run, &first_actor);std::thread t2(&SecondActor::run, &second_actor);std::thread t3(&ThirdActor::run, &third_actor);t1.join();t2.join();t3.join();return 0;
}

6、 Pipeline模式概述

Pipeline(流水線)模式是一種將一個復雜任務分解為多個獨立子任務,并讓這些子任務像流水線一樣依次執行的設計模式。每個子任務負責處理一部分工作,處理完后將結果傳遞給下一個子任務,最終完成整個復雜任務。這種模式可以提高系統的并發性能和可維護性,因為每個子任務可以獨立開發、測試和優化,而且不同的子任務可以并行執行。

應用場景

  • 數據處理流程:例如在圖像或視頻處理中,一個完整的處理流程可能包括圖像讀取、降噪、增強、裁剪等多個步驟,每個步驟可以作為一個獨立的子任務在流水線上執行。
  • 網絡請求處理:在網絡服務器中,一個請求可能需要經過接收、解析、驗證、業務邏輯處理、響應生成等多個階段,使用流水線模式可以高效地處理大量請求。

C++實現示例

以下是一個簡單的C++示例,模擬一個簡單的數據處理流水線,包含三個子任務:數據生成、數據處理和數據輸出。

#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>// 第一個階段:數據生成
class DataGenerator {
public:std::queue<int> outputQueue;std::mutex mtx;std::condition_variable cv;bool isFinished = false;void run() {for (int i = 0; i < 10; ++i) {std::this_thread::sleep_for(std::chrono::milliseconds(100));{std::unique_lock<std::mutex> lock(mtx);outputQueue.push(i);}cv.notify_one();}{std::unique_lock<std::mutex> lock(mtx);isFinished = true;}cv.notify_all();}
};// 第二個階段:數據處理
class DataProcessor {
public:DataGenerator& generator;std::queue<int> outputQueue;std::mutex mtx;std::condition_variable cv;bool isFinished = false;DataProcessor(DataGenerator& gen) : generator(gen) {}void run() {while (true) {int data;{std::unique_lock<std::mutex> lock(generator.mtx);generator.cv.wait(lock, [this] { return!generator.outputQueue.empty() || generator.isFinished; });if (generator.outputQueue.empty() && generator.isFinished) {break;}data = generator.outputQueue.front();generator.outputQueue.pop();}// 簡單的數據處理,這里將數據加倍data *= 2;{std::unique_lock<std::mutex> lock(mtx);outputQueue.push(data);}cv.notify_one();}{std::unique_lock<std::mutex> lock(mtx);isFinished = true;}cv.notify_all();}
};// 第三個階段:數據輸出
class DataOutputter {
public:DataProcessor& processor;DataOutputter(DataProcessor& proc) : processor(proc) {}void run() {while (true) {int data;{std::unique_lock<std::mutex> lock(processor.mtx);processor.cv.wait(lock, [this] { return!processor.outputQueue.empty() || processor.isFinished; });if (processor.outputQueue.empty() && processor.isFinished) {break;}data = processor.outputQueue.front();processor.outputQueue.pop();}std::cout << "Processed data: " << data << std::endl;}}
};int main() {DataGenerator generator;DataProcessor processor(generator);DataOutputter outputter(processor);std::thread generatorThread(&DataGenerator::run, &generator);std::thread processorThread(&DataProcessor::run, &processor);std::thread outputterThread(&DataOutputter::run, &outputter);generatorThread.join();processorThread.join();outputterThread.join();return 0;
}

代碼解釋

  1. DataGenerator類:負責生成數據,將生成的數據放入輸出隊列outputQueue,并通過條件變量cv通知下一個階段有新數據可用。
  2. DataProcessor類:從DataGenerator的輸出隊列中獲取數據,對數據進行處理(這里簡單地將數據加倍),然后將處理后的數據放入自己的輸出隊列,并通知下一個階段。
  3. DataOutputter類:從DataProcessor的輸出隊列中獲取數據,并將其輸出到控制臺。
  4. main函數:創建三個線程分別運行三個階段的任務,并等待所有線程執行完畢。

通過這種方式,數據在三個階段之間依次傳遞,形成了一個簡單的流水線。每個階段可以獨立運行,提高了系統的并發性能。

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

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

相關文章

【時時三省】(C語言基礎)習題2 scanf函數

山不在高&#xff0c;有仙則名。水不在深&#xff0c;有龍則靈。 ----CSDN 時時三省 用下面的scanf函數輸入數據&#xff0c;使a 3&#xff0c;b 7&#xff0c;x 8.5&#xff0c;y 71.82&#xff0c;c1 A&#xff0c;c2 x在鍵盤上應如何輸入? 分析第一個 scanf 函數&…

微信小程序計算屬性與監聽器:miniprogram-computed

小程序框架沒有提供計算屬性相關的 api &#xff0c;但是官方為開發者提供了拓展工具庫 miniprogram-computed。 該工具庫提供了兩個功能&#xff1a; 計算屬性 computed監聽器 watch 一、安裝 miniprogram-computed 在項目的根目錄下&#xff0c;使用如下命令&#xff0c;…

SOFAStack-00-sofa 技術棧概覽

SOFAStack 前言 大家好&#xff0c;我是老馬。 sofastack 其實出來很久了&#xff0c;第一次應該是在 2022 年左右開始關注&#xff0c;但是一直沒有深入研究。 最近想學習一下 SOFA 對于生態的設計和思考。 &#x1f31f; 核心項目 ?? SOFABoot GitHub: sofastack/sofa…

企業模板(QiMoban)是一個專注于企業官網搭建的高效平臺

企業模板(QiMoban.com )是一個專注于為企業提供高效、低成本網站建設解決方案的平臺&#xff0c;主要面向中小企業和創業者。其核心優勢在于幫助用戶快速搭建企業官網&#xff0c;提升品牌形象并拓展業務渠道。以下是關于企業模板(QiMoban.com )的詳細分析&#xff1a; 適用場…

Oracle 數據庫安全評估(DBSAT)簡明過程

下載DBSAT 從這里下載。 實際是從MOS中下載&#xff0c;即&#xff1a;Oracle Database Security Assessment Tool (DBSAT) (Doc ID 2138254.1)。 最新版本為3.1.0 (July 2024)&#xff0c;名為dbsat.zip&#xff0c;近45MB。 $ ls -lh dbsat.zip -rw-rw-r-- 1 oracle oins…

【Linux 維測專欄 1 -- Hung Task 分析與驗證】

文章目錄 Linux Hung Task 簡介1. Hung Task 概述2. D 狀態與 Hung Task3. Hung Task 的工作原理4. Hung Task 的配置5. Hung Task 的典型輸出6. Hung Task 的應用場景7. kernel 配置7.1 編譯選項7.2 參數控制7.3 驗證方法4. 擴展接口 8. 注意事項 Linux Hung Task 簡介 1. Hu…

GCC 預定義宏:解鎖編譯器的隱藏信息

GCC 預定義宏&#xff1a;解鎖編譯器的隱藏信息 在 GCC 編譯器中&#xff0c;有許多內置的預定義宏&#xff0c;它們可以提供編譯環境的信息&#xff0c;如文件名、行號、時間、版本等。這些宏在調試、日志記錄、條件編譯等場景中非常有用。本文將介紹常見的 GCC 預定義宏&…

公鏈開發費用及其構成內容詳析

在區塊鏈技術迅速發展的今天&#xff0c;公鏈&#xff08;Public Blockchain&#xff09;作為去中心化、不可篡改、高安全性的重要應用之一&#xff0c;在金融、供應鏈、游戲等多個領域得到了廣泛應用。然而&#xff0c;開發一條公鏈并非易事&#xff0c;它不僅需要高度專業技能…

Java求101-200之間有多少素數

Java學習筆記 今天看教程看到了這個題&#xff0c;對于一名打過算法競賽的選手還是很簡單的&#xff0c;但由于之前是c組的&#xff0c;所以用java寫一下&#xff0c;練一下手。 代碼&#xff1a; package com.itheima.hello;public class Test1 {public static void main(S…

DM 達夢上的日志挖掘 DBMS_LOGMNR

適用場景 在 DM 中&#xff0c;用戶可以使用 DBMS_LOGMNR 包對歸檔日志進行挖掘&#xff0c;重構出 DDL 和 DML 等操作&#xff0c;并通過獲取的信息進行更深入的分析&#xff1b;同樣&#xff0c;可以對歸檔日志文件進行恢復被誤操作的數據&#xff0c;并進行故障跟蹤&#x…

JavaWeb之WebSocket

目錄 一、 websocket 概念二、WebSocket原理三、WebSocket特點四、WebSocket應用場景五、Websocket基本使用1、創建Websocket對象2、Websocket事件3、Websocket方法4、前端服務程序 六、聊天室案例1、Tomcat版本&#xff1a;8.0.442、Maven 依賴&#xff1a;3、前端代碼4、后端…

Unity Shader編程】之透明物體渲染

以下是針對您提出的關于 Unity Shader 渲染 Pass 的查看方法、多個 Pass 的影響、Pass 的含義&#xff0c;以及 Unity 渲染物體的流程和處理多個透明/半透明/不透明物體的詳細解答。 1. Unity Shader 渲染 Pass 的查看方法 查看 Pass 的方法 通過 Shader 代碼&#xff1a; 打開…

字符指針的三道例題+算法改進

目錄 一.楊氏矩陣 1.初級 2.想把下標帶回來 二.字符串左旋 算法改進 三.判斷是否為字符串旋轉結果 算法改進 四. 3個字符函數 1.strcat 2.strncat 3.strstr 一.楊氏矩陣 數字矩陣&#xff0c;每行從左到右遞增&#xff0c;每列從上到下遞增&#xff0c;編寫程序在矩…

VSCode中搜索插件顯示“提取擴展時出錯。Failed to fetch”問題解決!

大致的問題如下&#xff0c;在VSCode的插件商店搜索插件時提示如下&#xff1a; 導致的情況有以下幾點&#xff1a; 1、代理問題&#xff0c;如果是代理引起的&#xff0c;可以繼續使用代理后也能搜索和安裝插件。 2、還有可能是你的所連接的網絡設置了防火墻&#xff0c;比較…

雙指針(2)—三數之和

文章目錄 題目解析解法&#xff08;排序雙指針&#xff09;&#xff1a;哈希解法附加Java代碼&#xff1a; 力扣題目&#xff1a;三數之和 題目解析 解法&#xff08;排序雙指針&#xff09;&#xff1a; **算法思路&#xff1a;** 本題與兩數之和類似&#xff0c;是?常經典的…

設計一套水產養殖系統

設計一套水產養殖系統 引言 水產養殖在全球糧食安全和經濟發展中日益重要。它不僅為不斷增長的人口提供了重要的蛋白質來源&#xff0c;還在許多地區創造了就業機會并促進了經濟增長 。全球超過一半的人類消費的海產品來自水產養殖&#xff0c;并且這一比例預計將繼續上升 。…

統計可重復列表中的TOP N

文章目錄 方案1&#xff1a;HashMap統計 全排序實現步驟&#xff1a;代碼實現&#xff1a;優缺點&#xff1a; 方案2&#xff1a;HashMap統計 最小堆&#xff08;優先隊列&#xff09;實現步驟&#xff1a;代碼實現&#xff1a;優缺點&#xff1a; 方案3&#xff1a;Java Str…

JVM 知識點梳理

JDK 、JRE、JVM JDK&#xff08; Java Development Kit &#xff09; Java開發工具包 JRE 開發命令工具&#xff08;運行java.exe、編譯javac.exe、javaw.exe&#xff09; JRE&#xff08; Java Runtime Environment &#xff09;Java運行環境 JVM Java核心類庫&#xff08;l…

淘寶歷史價格數據獲取指南:API 與爬蟲方案的合法性與效率對比

引言 在淘寶平臺的購物生態中&#xff0c;消費者希望通過了解商品歷史價格來判斷當前價格是否實惠&#xff0c;商家也需要借助歷史價格數據制定合理的營銷策略、分析市場趨勢。獲取淘寶商品歷史價格數據主要有 API 和爬蟲兩種方案&#xff0c;它們在合法性與效率上存在顯著差異…

DeepSeek-R1論文深度解析:純強化學習如何引爆LLM推理革命?

技術突破&#xff1a;從“無監督”到“自主進化”的跨越 paper &#xff1a;https://arxiv.org/pdf/2501.12948目錄 技術突破&#xff1a;從“無監督”到“自主進化”的跨越1 DeepSeek-R1-Zero&#xff1a; RLnoSFT1.1 R1-Zero&#xff1a; GRPO&#xff08;Group Relative Po…