欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

簡單聊聊C++中線程的原理與實現(xiàn)

 更新時間:2023年03月30日 09:19:48   作者:快樂有家  
C++11?引入了多線程支持,提供了一套基本的線程庫,包括線程、互斥量(mutex)、條件變量(condition_variable)等。這些組件可以幫助你在?C++?程序中實現(xiàn)并發(fā)和多線程編程,本文就來和大家簡單聊聊吧

在C++中有多種實現(xiàn)線程的方式

  • C++11提供的標準多線程方式;
  • 第三方庫(如:Boost.Thread);
  • 操作系統(tǒng)提供的多線程(如:Windows 線程 與 POSIX 線程(pthread))。

我們這里先了解的就是C++11提供的標準多線程方式。因為它提供了良好的跨平臺兼容性和簡潔的語法,已經滿足大多數(shù)需求。

從最簡單的開始

C++11 引入了多線程支持,提供了一套基本的線程庫,包括線程、互斥量(mutex)、條件變量(condition_variable)等。這些組件可以幫助你在 C++ 程序中實現(xiàn)并發(fā)和多線程編程。下面是一些基本概念和示例:

1.std::thread:

std::thread 是 C++11 中的線程類,用于創(chuàng)建和管理線程。您可以將一個函數(shù)作為參數(shù)傳遞給 std::thread 的構造函數(shù),該函數(shù)將在新線程中執(zhí)行。

#include <iostream>
#include <thread>

void hello() {
    std::cout << "Hello from thread!" << std::endl;
}

int main() {
    std::thread t(hello); // 創(chuàng)建一個新線程,執(zhí)行 hello 函數(shù)
    t.join(); // 等待線程結束
    return 0;
}

2.std::mutex:

std::mutex 是互斥量類,用于保護共享資源的訪問。當多個線程需要訪問共享資源時,使用互斥量可以確保每次只有一個線程訪問資源,從而避免數(shù)據(jù)競爭和其他并發(fā)問題。

#include <iostream>
#include <mutex>
#include <thread>

std::mutex mtx; // 互斥量

void print_block(int n, char c) {
    mtx.lock(); // 鎖定互斥量
    for (int i = 0; i < n; ++i) {
        std::cout << c;
    }
    std::cout << std::endl;
    mtx.unlock(); // 解鎖互斥量
}

int main() {
    std::thread t1(print_block, 50, '*');
    std::thread t2(print_block, 50, '$');
    t1.join();
    t2.join();
    return 0;
}

3.std::lock_guard:

std::lock_guard 是一個 RAII(Resource Acquisition Is Initialization)包裝類,用于自動管理互斥量的鎖定和解鎖。當創(chuàng)建 std::lock_guard 對象時,它將自動鎖定互斥量,當對象銷毀時,它將自動解鎖互斥量。

void print_block(int n, char c) {
    std::lock_guard<std::mutex> lock(mtx); // 自動鎖定互斥量
    for (int i = 0; i < n; ++i) {
        std::cout << c;
    }
    std::cout << std::endl;
    // 自動解鎖互斥量(lock_guard 對象銷毀時)
}

4.std::condition_variable:

std::condition_variable 是一個條件變量類,用于在線程之間同步操作。它可以與 std::mutex 配合使用,實現(xiàn)線程間的等待和通知機制。

#include <iostream>
#include <condition_variable>
#include <mutex>
#include <thread>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void print_id(int id) {
    std::unique_lock<std::mutex> lck(mtx); 
    cv.wait(lck, [] { return ready; }); // 等待 ready 變?yōu)?true 
    std::cout << "thread " << id << std::endl; 
} 

void go() { 
    std::unique_lock<std::mutex> lck(mtx);
    ready = true; 
    cv.notify_all();// 通知所有等待的線程 
}

int main() {
    std::thread threads[10];
    for (int i = 0; i < 10; ++i) {
        threads[i] = std::thread(print_id, i); // 啟動 10 個線程 
    }
    
    go(); // 通知所有線程開始執(zhí)行

    for (auto& th : threads) {
        th.join(); 
    }
    return 0;
}

在這個示例中,我們創(chuàng)建了 10 個線程,每個線程在啟動后等待一個條件變量。主線程通過調用 go 函數(shù)將條件變量的狀態(tài)設置為 true 并通知所有等待的線程,使它們開始執(zhí)行。

5.std::future 和 std::async:

std::futurestd::async 是 C++11 提供的用于異步操作的類。std::async 可以異步地執(zhí)行一個函數(shù),并返回一個 std::future 對象,該對象表示該函數(shù)的返回值。您可以通過調用 std::future::get() 來等待函數(shù)執(zhí)行完成并獲取其返回值。

#include <iostream>
#include <future>

int sum(int a, int b) {
    return a + b;
}

int main() {
    std::future<int> result = std::async(sum, 10, 20); // 異步執(zhí)行 sum 函數(shù)
    int value = result.get(); // 等待執(zhí)行完成并獲取返回值
    std::cout << "The result is: " << value << std::endl;
    return 0;
}

這個簡單的示例展示了如何使用 std::async 異步地執(zhí)行一個求和函數(shù),然后通過std::future 獲取其結果。

C++11 的多線程支持功能使得在 C++ 中實現(xiàn)并發(fā)編程變得更加簡單。通過這些基本組件,您可以根據(jù)需要構建更復雜的并發(fā)程序。

C++11的線程只有這么簡單嗎?

是也不是。C++11 中的多線程庫確實相對簡單,但這只是表面現(xiàn)象。實際上,它們?yōu)閺碗s的多線程程序提供了基礎。前面已經介紹了一些基本的多線程組件,例如 std::threadstd::mutex、std::condition_variablestd::futurestd::async。但是,還有一些其他的組件和技巧可能會對你有幫助:

1.std::atomic:

C++11 引入了原子類型(std::atomic),用于實現(xiàn)原子操作,即在多線程環(huán)境中不會被中斷的操作。原子類型在多線程中特別有用,因為它們可以避免數(shù)據(jù)競爭和其他并發(fā)問題。

示例:

#include <iostream>
#include <atomic>
#include <thread>

std::atomic<int> counter(0);

void increase_counter() {
    for (int i = 0; i < 1000; ++i) {
        ++counter;
    }
}

int main() {
    std::thread t1(increase_counter);
    std::thread t2(increase_counter);

    t1.join();
    t2.join();

    std::cout << "Counter: " << counter << std::endl;
    return 0;
}

2.std::call_once:

std::call_once 是一個用于確保在多線程環(huán)境中某個函數(shù)只被調用一次的工具。它需要一個 std::once_flag 變量作為參數(shù),該變量用于跟蹤函數(shù)是否已被調用。

示例:

#include <iostream>
#include <mutex>
#include <thread>

std::once_flag flag;

void do_something() {
    std::cout << "Called once" << std::endl;
}

void call_do_something() {
    std::call_once(flag, do_something);
}

int main() {
    std::thread t1(call_do_something);
    std::thread t2(call_do_something);

    t1.join();
    t2.join();

    return 0;
}

3.線程局部存儲:

C++11 支持線程局部存儲,即每個線程擁有自己的變量副本。使用 thread_local 關鍵字可以定義一個線程局部變量。這對于某些需要每個線程擁有獨立狀態(tài)的應用場景非常有用。

示例:

#include <iostream>
#include <thread>

thread_local int counter = 0;

void increase_counter() {
    ++counter;
    std::cout << "Counter: " << counter << " in thread " << std::this_thread::get_id() << std::endl;
}

int main() {
    std::thread t1(increase_counter);
    std::thread t2(increase_counter);

    t1.join();
    t2.join();

    return 0;
}

以上是 C++11 多線程庫中的一些其他組件和技巧。雖然這些組件相對簡單,但它們?yōu)閷崿F(xiàn)復雜的多線程應用提供了基礎。掌握這些基本概念后,你可以根據(jù)自己的需求組合這些組件以實現(xiàn)更高級的功能。以下是一些可能對你有幫助的高級用法:

線程池

線程池是一種允許您在一組線程中重用線程以執(zhí)行任務的技術。這可以減少線程創(chuàng)建和銷毀的開銷,從而提高性能。C++11 沒有提供內置的線程池功能,但您可以使用基本的多線程組件自己實現(xiàn)一個,或者使用第三方庫(例如 Boost.Asio)。

并行算法

C++17 標準引入了并行算法庫,它提供了一些與 STL 算法類似的并行版本,以支持多線程并行執(zhí)行。這使得實現(xiàn)并行計算變得更加簡單。例如,您可以使用 std::sort 的并行版本 std::execution::par 對大數(shù)據(jù)集進行排序。

示例:

#include <iostream>
#include <vector>
#include <algorithm>
#include <execution>
#include <random>

int main() {
    std::vector<int> data(100000);
    std::random_device rd;
    std::mt19937 gen(rd());

    std::generate(data.begin(), data.end(), [&]() { return gen() % 1000; });

    std::sort(std::execution::par, data.begin(), data.end());

    // 現(xiàn)在 data 已經被排序
    return 0;
}

lock_guard 和 scoped_lock:

std::lock_guard 是一個簡化互斥鎖管理的 RAII 封裝。當您創(chuàng)建一個 lock_guard 對象時,它將自動鎖定給定的互斥鎖,并在銷毀時自動解鎖。這有助于避免死鎖和忘記解鎖。

std::scoped_lock 是 C++17 引入的一個改進版的 lock_guard,用于同時鎖定多個互斥鎖,避免死鎖。

std::shared_mutex 和 std::shared_lock:

std::shared_mutex 是一種特殊類型的互斥鎖,允許多個線程同時以共享模式訪問資源。std::shared_lock 是與 std::shared_mutex 配合使用的鎖對象,允許您在共享模式或獨占模式下鎖定資源。

以上是 C++11 多線程庫的一些高級用法。熟練掌握這些組件和技巧可以幫助您實現(xiàn)更加高效、可擴展和健壯的多線程應用。

大體其實就這些,另外在設計時還需要注意的是:

避免死鎖:

在多線程編程中,死鎖是一個常見的問題,它發(fā)生在兩個或多個線程相互等待對方釋放資源時。為了避免死鎖,請確保使用鎖的順序一致,避免嵌套鎖,并盡量減少鎖的使用范圍。

數(shù)據(jù)競爭與內存模型:

在多線程環(huán)境中,數(shù)據(jù)競爭是一個潛在的問題。當多個線程同時訪問共享數(shù)據(jù)且至少有一個線程對數(shù)據(jù)進行修改時,就會發(fā)生數(shù)據(jù)競爭。避免數(shù)據(jù)競爭的方法包括使用互斥鎖、原子操作或者線程局部存儲。

此外,C++11 引入了內存模型,用于描述多線程中的內存訪問行為。內存模型包括原子操作的內存順序,例如 std::memory_order_relaxedstd::memory_order_acquirestd::memory_order_release。在大多數(shù)情況下,默認的內存順序已經足夠使用,但在某些高級應用場景下,理解和使用內存模型可以幫助您實現(xiàn)更高效的代碼。

性能與可伸縮性:

在編寫多線程程序時,需要權衡性能和可伸縮性。線程之間的通信和同步會導致性能損失,因此您需要在使用更多線程以提高并發(fā)性能時,盡量減少同步和通信的開銷。

異常安全:

在多線程環(huán)境中,處理異常尤為重要。在一個線程中發(fā)生異常時,其他線程可能仍在繼續(xù)執(zhí)行。確保在多線程中正確處理異常,例如使用 try-catch 塊捕獲異常,并確保鎖和資源在異常發(fā)生時得到正確的釋放。

第三方庫和框架:

除了 C++ 標準庫提供的多線程支持外,還有一些第三方庫和框架提供了更高級或特定領域的多線程功能。例如,Boost.Thread 庫提供了類似于 C++11 多線程庫的功能,但在某些方面更為強大。Intel 的 Threading Building Blocks (TBB) 是另一個廣泛使用的并行編程庫。

P.S. 再來點與之無關緊要的小知識

join()既然是等待子線程完成,為什么不叫wait_thread()之類的? 而且join本身的單詞是加入,有點感覺格格不入。

因為在多線程編程中,join 方法的命名來源于它的作用:將一個子線程加入(join)到主線程或其他線程,等待這個子線程完成。這種“加入”的概念實際上是指當前線程(通常是主線程)等待另一個線程(子線程)完成它的任務。在子線程完成任務之前,當前線程會阻塞等待。因此,join 這個名字來源于將子線程與等待它的線程連接在一起的過程。簡單來說,當在瘋狂星期四這天的公司樓下KFC里,在你排隊買快樂時,有你的領導插隊(join進來),你必須等它完成的,所以這也就是等待的本意。

wait()

std::condition_variable::wait() 是一個成員函數(shù),用于阻塞當前線程,直到條件變量被通知。wait() 函數(shù)通常與 std::unique_lock<std::mutex>std::mutex 配合使用,以便在等待期間自動解鎖互斥量??梢詡鬟f一個謂詞函數(shù)給 wait(),以便在條件變量被通知后檢查是否滿足繼續(xù)執(zhí)行的條件。

notify_all()notify_one

std::condition_variable::notify_all() 是一個成員函數(shù),用于喚醒所有等待當前條件變量的線程。當某個條件滿足時,可以調用 notify_all() 通知所有等待的線程繼續(xù)執(zhí)行。這是一種線程之間協(xié)作的方式。

std::condition_variable::notify_one() 也是一個成員函數(shù),用于喚醒一個正在等待該條件變量的線程。與之相對的,notify_all 是喚醒所有正在等待該條件變量的線程。在某些情況下,您可能只需要喚醒一個等待的線程,而不是所有線程,這時候就可以使用 notify_one。

再聊聊第三方庫(如:Boost.Thread)方式

#include <iostream>
#include <boost/thread.hpp>

void print_hello() {
    std::cout << "Hello from thread!" << std::endl;
}

int main() {
    boost::thread thread(print_hello);
    thread.join();

    std::cout << "Hello from main!" << std::endl;
    return 0;
}

最后的戰(zhàn)役:操作系統(tǒng)方式

1.POSIX 線程(pthread):

POSIX 線程是基于 POSIX 標準的一種多線程實現(xiàn),它在類 Unix 系統(tǒng)(如 Linux、macOS)中廣泛使用。pthread 庫提供了用于創(chuàng)建線程、同步、互斥鎖等多線程功能的函數(shù)。然而,由于它是用 C 語言編寫的,所以在 C++ 中使用時可能不夠直觀。以下是一個簡單的使用 POSIX 線程的例子:

#include <iostream>
#include <pthread.h>

void* print_hello(void* arg) {
    std::cout << "Hello from thread!" << std::endl;
    return nullptr;
}

int main() {
    pthread_t thread;
    pthread_create(&thread, nullptr, print_hello, nullptr);
    pthread_join(thread, nullptr);

    std::cout << "Hello from main!" << std::endl;
    return 0;
}

2.Windows 線程:

在 Windows 操作系統(tǒng)中,可以通過 Windows API 來創(chuàng)建和管理線程。Windows API 提供了一組用于線程管理、同步和互斥的函數(shù)。以下是一個簡單的使用 Windows 線程的例子:

#include <iostream>
#include <windows.h>

DWORD WINAPI print_hello(LPVOID lpParam) {
    std::cout << "Hello from thread!" << std::endl;
    return 0;
}

int main() {
    HANDLE thread = CreateThread(nullptr, 0, print_hello, nullptr, 0, nullptr);
    WaitForSingleObject(thread, INFINITE);
    CloseHandle(thread);

    std::cout << "Hello from main!" << std::endl;
    return 0;
}

由于這不是我們的重點戰(zhàn)場,簡單了解一下就完事,當你必須使用它時這個文章就沒必要看了。

到此這篇關于簡單聊聊C++中線程的原理與實現(xiàn)的文章就介紹到這了,更多相關C++線程內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C++實現(xiàn)LeetCode(42.收集雨水)

    C++實現(xiàn)LeetCode(42.收集雨水)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(42.收集雨水),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下
    2021-07-07
  • C++ 中滾動條的滾動問題

    C++ 中滾動條的滾動問題

    本文主要通過一個示例,給大家介紹了C++中滾動條的滾動問題,以及相關參數(shù)的解釋,非常的詳細,有需要的小伙伴可以參考下。
    2015-06-06
  • c++11中regex正則表達式示例簡述

    c++11中regex正則表達式示例簡述

    這篇文章主要給大家介紹了關于c++11中regex正則表達式的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用c++11具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-11-11
  • C++中cin的返回值問題

    C++中cin的返回值問題

    這篇文章主要介紹了C++中cin的返回值問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • C++?OpenCV實現(xiàn)boxfilter方框濾波的方法詳解

    C++?OpenCV實現(xiàn)boxfilter方框濾波的方法詳解

    box?filter的作用很簡單,即對局部區(qū)域求平均,并把值賦給某個點,一般我們賦給區(qū)域中心。本文將用C++實現(xiàn)boxfilter方框濾波,需要的可以了解一下
    2022-10-10
  • C語言棧順序結構實現(xiàn)代碼

    C語言棧順序結構實現(xiàn)代碼

    一個能夠自動擴容的順序結構的棧 ArrStack 實例 (GCC編譯),有需要的朋友可以參考一下
    2013-10-10
  • C++?Qt利用GPU加速計算的示例詳解

    C++?Qt利用GPU加速計算的示例詳解

    這篇文章主要為大家詳細介紹了在?C++?和?Qt?中如何利用GPU加速計算,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-03-03
  • C++ Qt開發(fā)之ComboBox下拉組合框組件用法詳解

    C++ Qt開發(fā)之ComboBox下拉組合框組件用法詳解

    Qt 是一個跨平臺C++圖形界面開發(fā)庫,利用Qt可以快速開發(fā)跨平臺窗體應用程序,在Qt中,ComboBox(組合框)是一種常用的用戶界面控件,它提供了一個下拉列表,允許用戶從預定義的選項中選擇一個,本文給大家介紹QComboBox類的一些常用方法,需要的朋友可以參考下
    2023-12-12
  • C++?反匯編之關于Switch語句的優(yōu)化措施

    C++?反匯編之關于Switch語句的優(yōu)化措施

    這篇文章主要介紹了C++?反匯編之關于Switch語句的優(yōu)化措施,利用三種優(yōu)化來降低樹高度,誰的效率高就優(yōu)先使用誰,三種優(yōu)化都無法匹配才會使用判定樹,具體內容詳情跟隨小編一起看看吧
    2022-01-01
  • C語言菜鳥基礎教程之a++與++a

    C語言菜鳥基礎教程之a++與++a

    很多同學在學習c語言的時候是不是會碰到a++和++a都有甚么作用啊。今天我們就來探討下
    2017-10-10

最新評論