亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

深入解析C++中的std::thread的使用

 更新時間:2023年04月20日 10:19:08   作者:つ栺尖篴夢ゞ  
這篇文章主要介紹了C++中的std::thread的使用,在C++11新標準中,可以簡單通過使用thread庫,來管理多線程,本文通過實例代碼給大家詳細講解,需要的朋友可以參考下

std::thread簡介

C++11之前,window和linux平臺分別有各自的多線程標準,使用C++編寫的多線程往往是依賴于特定平臺的。

  • Window平臺提供用于多線程創(chuàng)建和管理的win32 api;
  • Linux下則有POSIX多線程標準,Threads或Pthreads庫提供的API可以在類Unix上運行;

在C++11新標準中,可以簡單通過使用thread庫,來管理多線程。thread庫可以看做對不同平臺多線程API的一層包裝;因此使用新標準提供的線程庫編寫的程序是跨平臺的。

一、C++11 線程創(chuàng)建

  • 每一個 C++11 程序都包含一個主線程即 main() 函數(shù),在 C++11 中可以通過創(chuàng)建 std::thread 對象來創(chuàng)建新的線程,每個 std::thread 對象都可以與一個線程相關(guān)聯(lián)。
  • 需要引用的頭文件:
#include <thread>

二、std::thread 的構(gòu)造函數(shù)中接收什么參數(shù)?

  • 可以給 std::thread 對象添加函數(shù),這個回調(diào)函數(shù)將在這個新線程啟動時執(zhí)行。這些回調(diào)可以是:
    • 函數(shù)指針;
    • 函數(shù)對象;
    • Lambda 函數(shù)。
  • 創(chuàng)建 thread 對象:
std::thread thObj(<CALLBACK>);
  • 新線程將在創(chuàng)建新對象后立即啟動,并將并行地執(zhí)行(當參數(shù))傳遞給線程的回調(diào)函數(shù)。此外,任何線程都可以通過調(diào)用某線程對象上的 join( ) 函數(shù)來等待此線程退出。
  • 來看一個例子,主線程將創(chuàng)建另外一個線程,創(chuàng)建這個新線程后,主線程會在控制臺上打印一些數(shù)據(jù),然后等待新創(chuàng)建的線程退出。
  • 使用函數(shù)指針創(chuàng)建線程:
#include <thread>

void thread_function() {
    for(int i = 0; i < 10000; i++);
        std::cout<<"thread function Executing"<<std::endl;
}

int main() {
    std::thread threadObj(thread_function);
    for(int i = 0; i < 10000; i++);
        std::cout<<"Display From MainThread"<<std::endl;
    threadObj.join();    
    std::cout<<"Exit of Main function"<<std::endl;
    return 0;
}
  • 使用函數(shù)對象創(chuàng)建線程:
#include <iostream>
#include <thread>
class DisplayThread {
public:
    void operator()() {
        for(int i = 0; i < 10000; i++)
            std::cout<<"Display Thread Executing"<<std::endl;
    }
};

int main() {
    std::thread threadObj( (DisplayThread()) );
    for(int i = 0; i < 10000; i++)
        std::cout<<"Display From Main Thread "<<std::endl;
    std::cout<<"Waiting For Thread to complete"<<std::endl;
    threadObj.join();
    std::cout<<"Exiting from Main Thread"<<std::endl;
    return 0;
}
  • 使用 Lambda 函數(shù)創(chuàng)建線程:
#include <iostream>
#include <thread>
int main() {
    int x = 9;
    std::thread threadObj([]{
            for(int i = 0; i < 10000; i++)
                std::cout<<"Display Thread Executing"<<std::endl;
            });

    for(int i = 0; i < 10000; i++)
        std::cout<<"Display From Main Thread"<<std::endl;

    threadObj.join();
    std::cout<<"Exiting from Main Thread"<<std::endl;
    return 0;
}
  • 如何區(qū)分線程:
    • 每個 std::thread 對象都有一個 ID,使用下面的函數(shù)可以獲取:
std::thread::get_id()

獲取當前線程的 ID:

std::this_thread::get_id()
  • 如果 std::thread 對象沒有和任何對象關(guān)聯(lián),則 get_id() 函數(shù)會返回默認構(gòu)造的 std::thread::id 對象,即“非線程”。std::thread::id 是一個對象,它也可以在控制臺上進行比較和打印:
#include <iostream>
#include <thread>
void thread_function() {
    std::cout<<"Inside Thread :: ID  = "<<std::this_thread::get_id()<<std::endl;    
}
int main() {
    std::thread threadObj1(thread_function);
    std::thread threadObj2(thread_function);

    if(threadObj1.get_id() != threadObj2.get_id())
        std::cout<<"Both Threads have different IDs"<<std::endl;

    std::cout<<"From Main Thread :: ID of Thread 1 = "<<threadObj1.get_id()<<std::endl;    
    std::cout<<"From Main Thread :: ID of Thread 2 = "<<threadObj2.get_id()<<std::endl;    

    threadObj1.join();    
    threadObj2.join();    
    return 0;
}

三、std::thread 的搭配用法

① std::promise

  • 為了在不同的線程之間傳遞數(shù)據(jù),C++ 引入了 std::promise 和 std::future 這兩種數(shù)據(jù)結(jié)構(gòu),在頭文件 <future> 中包含。
  • promise 是一個范型的數(shù)據(jù)結(jié)構(gòu),你可以定義一個整形的 promise:promise,這意味著線程之間傳遞的值是整形。promise 的 get_future() 方法返回一個 future 數(shù)據(jù)結(jié)構(gòu),從這個 future 數(shù)據(jù)結(jié)構(gòu)可以獲取設(shè)置給 promise 的值:
#include <iostream>
#include <future>
#include <thread>

using namespace std;

int main() {
  promise<int> a_promise;
  auto a_future = a_promise.get_future();
  a_promise.set_value(10);
  cout << a_future.get() << endl;
  cout << "after get()" << endl;
  return 0;
}

輸出結(jié)構(gòu)是:

10
after get()

  • 實際上,上面的例子并沒有使用線程,但是很好得展示了 promise 和 future 之間的關(guān)系。更復雜一點的使用場景可能如下:
    • 主線程定義一個 promise,命名為 p;
    • 主線程調(diào)用 p.get_future(),并把返回值保存為引用 f;
    • 主線程啟動一個子線程,并把 p 作為啟動參數(shù)傳給子線程;
    • 主線程調(diào)用 f.get(),但是此時子線程還未將數(shù)據(jù)放入 promise 內(nèi),所以主線程掛起;
    • 子線程執(zhí)行完,獲取到結(jié)果,并把結(jié)果寫入 p;
    • 主線程從 f.get() 的調(diào)用中被喚醒,獲取到子線程寫入 p 的值,繼續(xù)執(zhí)行。

② std::packaged_task

C++11 很貼心地提供 packaged_task 類型,可以不用直接使用 std::thread 和 std::promise,直接就能夠生成線程,派遣任務:

#include <iostream>
#include <future>

using namespace std;

int f() {
  string hi = "hello, world!";
  cout << hi << endl;
  return hi.size();
}

int main() {
  packaged_task<int ()> task(f);
  auto result = task.get_future();

  task();

  cout << result.get() << endl;

  return 0;
}

運行結(jié)果為:

hello, world!
13

③ std::async

  • std::packaged_task 要求自己啟動任務,比如要顯示調(diào)用 task(),如果連這一步都想省了的話,可以使用 std:async:
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <future> 

template <typename RandomIt>

int parallel_sum(RandomIt beg, RandomIt end) {
    auto len = end - beg;
    if (len < 1000) 
        return std::accumulate(beg, end, 0);

    RandomIt mid = beg + len/2;
    auto handle = std::async(std::launch::async,
                             parallel_sum<RandomIt>, mid, end);
    int sum = parallel_sum(beg, mid);
    return sum + handle.get();
}

int main() {
    std::vector<int> v(10000, 1);
    std::cout << "The sum is " << parallel_sum(v.begin(), v.end()) << '\n';
}

運行結(jié)果:

The sum is 10000

④ std::this_thread

  • C++11 專門提供了一個命名空間 std::this_thread 來表示當前線程。
  • std::this_thread 提供了幾個方法可以對線程做一定的控制:
    • get_id(),獲取線程 id;
    • yield(),釋放執(zhí)行權(quán);
    • sleep_for(),使線程沉睡一定時間。
#include <iostream>
#include <future>
#include <thread>
using namespace std;

int f(promise<int> my_promise) {
  string hi = "hello, world!";

  my_promise.set_value(hi.size());

  this_thread::sleep_for(0.1s);
  cout << hi << endl;
}

int main() {
  promise<int> f_promise;

  auto result = f_promise.get_future();

  thread f_thread(f, move(f_promise));
  cout << result.get() << endl;

  f_thread.join();

  return 0;
}

到此這篇關(guān)于深入解析C++中的std::thread的使用的文章就介紹到這了,更多相關(guān)C++ std::thread使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論