C++11並發編程:多線程std::thread

2021-02-20 碼農code之路
一:概述

C++11引入了thread類,大大降低了多線程使用的複雜度,原先使用多線程只能用系統的API,無法解決跨平臺問題,一套代碼平臺移植,對應多線程代碼也必須要修改。現在在C++11中只需使用語言層面的thread可以解決這個問題。

所需頭文件< thread >

二:構造函數

1.默認構造函數
thread() noexcept
一個空的std::thread執行對象

2.初始化構造函數
template
explicit thread(Fn&& fn, Args&&… args);
創建std::thread執行對象,線程調用threadFun函數,函數參數為args。

void threadFun(int a)
{
    cout << "this is thread fun !" << endl;
}

thread t1(threadFun, 2);

3.拷貝構造函數
thread(const thread&) = delete;
拷貝構造函數被禁用,std::thread對象不可拷貝構造

void threadFun(int& a)
{
    cout << "this is thread fun !" << endl;
}

int value = 2;
thread t1(threadFun, std::ref(value));

4.Move構造函數
thread(thread&& x)noexcept
調用成功原來x不再是std::thread對象

void threadFun(int& a)
{
    cout << "this is thread fun !" << endl;
}

int value = 2;
thread t1(threadFun, std::ref(value));
thread t2(std::move(t1));
t2.join();

三:成員函數

1.get_id()
獲取線程ID,返回類型std::thread::id對象。

thread t1(threadFun);
thread::id threadId = t1.get_id();
cout << "線程ID:" << threadId << endl;


ostringstream   oss;
oss << t1.get_id();
string strId = oss.str();
unsigned long long tid = stoull(strId);
cout << "線程ID:" << tid << endl;

2.join()
創建線程執行線程函數,調用該函數會阻塞當前線程,直到線程執行完join才返回。

thread t1(threadFun);
t1.join()  

3.detach()
detach調用之後,目標線程就成為了守護線程,駐留後臺運行,與之關聯的std::thread對象失去對目標線程的關聯,無法再通過std::thread對象取得該線程的控制權。

4.swap()
交換兩個線程對象

thread t1(threadFun1);
thread t2(threadFun2);
cout << "線程1的ID:" << t1.get_id() << endl;
cout << "線程2的ID:" << t2.get_id() << endl;

t1.swap(t2);

cout << "線程1的ID:" << t1.get_id() << endl;
cout << "線程2的ID:" << t2.get_id() << endl;

5.hardware_concurrency()
獲得邏輯處理器儲量,返回值為int型

int coreNum = thread::hardware_concurrency();

四:使用

1.創建線程

void threadFun1()
{
    cout << "this is thread fun1 !" << endl;
}

int main()
{
    thread t1(threadFun1);
    t1.join();

    getchar();
    return 1;
}

2.創建線程,傳參

void threadFun1(int v)
{
    cout << "this is thread fun1 !" << endl;
    cout << v << endl;
}

int main()
{
    int value = 6;
    thread t1(threadFun1, value);
    t1.join();

    getchar();
    return 1;
}

需要注意,變量int value 和int v 做變量傳遞時並不是引用,而是對變量做了拷貝,所以在傳遞給int v前,int value不能出作用域(釋放了內存),join(),可以保證int value變量釋放內存,如果使用detach(),可能存在這種情況。

3.創建線程,引用傳參

void threadFun1(int& v)
{
    cout << "this is thread fun1 !" << endl;
    cout << v << endl;
}

int main()
{
    int value = 6;
    thread t1(threadFun1, std::ref(value));
    t1.join();

    getchar();
    return 1;
}

4.創建建線程,線程函數為類成員函數

class Object
{
public:
    Object()
    {
        cout << "構造函數" << endl;
    }

    ~Object()
    {
        cout << "析構函數" << endl;
    }

    void fun(string info)
    {
        cout << info << endl;
    }

};

int main()
{

    Object obj;
    string str = "我是一個類的成員函數!";
    thread t1(&Object::fun, &obj, str);
    t1.join();

    getchar();
    return 1;
}

相關焦點

  • UNIX(多線程):03--- 認識std::thread
    <thread> 頭文件摘要<thread> 頭文件聲明了 std::thread 線程類及 std::swap (交換兩個線程對象)輔助函數。另外命名空間 std::this_thread 也聲明在 <thread> 頭文件中。
  • C++並發與多線程__C++如何線程創建線程以及函數join()和detach()用法和區別
    主線程是從main()函數開始運行,main()函數就可以看做主線程的入口函數。1. C++如何創建一個線程。創建一個最簡單的線程只需要注意三點:第一:需要包含thread頭文件;第二:需要提供一個線程入口函數;第三:我們直接在main函數中創建thread。
  • 線程安全之std::atomic探索
    多線程的數據訪問一直很讓程式設計師們頭大,有什麼簡便方法來實現多線程間的通呢?
  • 多線程編程(1):從thread開始,邁入多線程的大門
    ❝觀前提醒,小屏手機橫屏有助於提升閱讀體驗❞經過千呼萬喚,終於在C++11中,引入了線程庫std::thread。本文要完成兩個目標:使用std::thread在如下的demo中,在主線程中使用std::thread創建3個子線程,線程入口函數是do_some_word,在主線程運行結束前等待子線程結束。
  • UNIX(多線程):07---線程啟動、結束,創建線程多法、join,detach
    線程啟動、結束,創建線程多法、join,detach範例演示線程運行的開始和結束#include
  • c++11新特性,所有知識點都在這了!
    ; std::bind & lambda表達式c++11新增了std::function、std::bind、lambda表達式等封裝使函數調用更加方便,詳細介紹請看:搞定c++11新特性std::function和lambda表達式模板的改進C++11
  • UNIX(多線程):14---理解線程構造函數
    第一參數的類型並不是c語言中的函數指針(c語言傳遞函數都是使用函數指針),在c++11中,增加了可調用對象(Callable Objects)的概念,總的來說,可調用對象可以是以下幾種情況:函數指針示例void function_1() {}void function_2(int i) {}void
  • C++多線程編程之創建線程的幾種方法
    #include <iostream>#include <thread>using namespace std;// 自己創建的線程也要從一個函數(初始函數)開始運行void myprint(){    cout << "我的線程開始執行了\n";
  • C++11線程、鎖和條件變量
    std::thread類代表了一個可執行的線程,它來自頭文件<thread>。與其它創建線程的API(比如 Windows API中的CreateThread)不同的是, 它可以使用普通函數、lambda函數以及仿函數(實現了operator()函數的類)。
  • 多線程 | Rust學習筆記
    現代的 CPU基本都是多核結構,為了充分利用多核的能力,多線程都是繞不開的話題。無論是同步或是異步編程,與多線程相關的問題一直都是困難並且容易出錯的,本質上是因為多線程程序的複雜性,特別是競爭條件的錯誤,使得錯誤發生具備一定的隨機性,而隨著程序的規模越來越大,解決問題的難度也隨之越來越高。C/C++將同步互斥,以及線程通信的問題全部交給了程式設計師。
  • 詳解 C++ 多線程的condition_variable
    當 std::condition_variable 對象的某個 wait 函數被調用的時候,它使用 std::unique_lock(通過 std::mutex) 來鎖住當前線程。當前線程會一直被阻塞,直到另外一個線程在相同的 std::condition_variable 對象上調用了 notification 函數來喚醒當前線程。
  • Java 並發編程之美-線程相關的基礎知識
    借用 Java 並發編程實踐中的話:編寫正確的程序並不容易,而編寫正常的並發程序就更難了;相比於順序執行的情況,多線程的線程安全問題是微妙而且出乎意料的
  • 走進C++11(三十七)原子操作之 std::atomic
    C++11提供了一個原子類型std::atomic<T>,可以使用任意類型作為模板參數,C++11內置了整型的原子變量
  • Python並發編程很簡單,一文搞清如何使用構造器創建線程
    上次已經和大家探討了關於進程和線程的區別和聯繫相關的東東,今天呢,咱們再次回到Python哦,和大家一起聊聊如何進行Python並發編程哦,大家也可以理解為如何在Python中進行多線程編程哦!好啦,廢話少說,咱們就開始吧!
  • C++並發condition_variable
    有意修改變量的線程必須獲得 std::mutex (常通過 std::lock_guard )在保有鎖時進行修改在 std::condition_variable 上執行 notifyone 或 notify_all (不需要為通知保有鎖)即使共享變量是原子的,也必須在互斥下修改它,以正確地發送修改至等待的線程。
  • C+標準庫 std:thread 的簡單使用,一文搞定還不簡單?
    std::thread是 C++ 11 新引入的標準線程庫。在同樣是 C++ 11 新引入的 lambda 函數的輔助下,std::thread用起來特別方便: int a = 1; std::thread thread([a](int b) { return a + b; }, 2);
  • 走進C++11(三十)標準化條件變量 -- condition_variable
    這篇文章是有關線程與並發的最後一篇文章,隨後會綜合之前講的,完成一個小例子:如何用幾十行代碼實現一個線程池。
  • Java並發編程:多線程如何實現阻塞與喚醒
    線程的阻塞和喚醒在多線程並發過程中是一個關鍵點,當線程數量達到很大的數量級時,並發可能帶來很多隱蔽的問題。如何正確暫停一個線程,暫停後又如何在一個要求的時間點恢復,這些都需要仔細考慮的細節。
  • c++中與操作時間開銷專題及常見問題 - CSDN
    C++多線程編程視頻課程學習筆記,適用於具有C++11基礎的學者,開發環境VS2017。1.有時候太多的線程,效率反而會降低,上下文切換會佔用太多沒有意義的時間。因為主線程是自動啟動的,所以一個進程最少有一個線程(主線程)。多線程程序可以同時做多件事,所以運行效率高。但是到底有多高,並不是一個很容易評估和量化的東西。大家仍舊需要在實際編程中,進行體會和調整優化。有時候,多個線程訪問同一個資源,多線程效率的提升不明顯。
  • C++11多線程編程(三)——lock_guard和unique_lock
    如果熟悉C++多線程的童鞋可能有了解到實現的互斥鎖的機制還有這個寫法lock_guard<