C++11/14 線程的創(chuàng)建與分離的實(shí)現(xiàn)
線程的創(chuàng)建
讓我們看看示例代碼(t1.cpp).
#include <iostream>
#include <thread>
void thread_function()
{
std::cout << "thread function\n";
}
int main()
{
std::thread t(&thread_function); // 線程 t 開(kāi)始運(yùn)行
std::cout << "main thread\n";
t.join(); // 主線程等待子線程結(jié)束
return 0;
}
代碼在linux系統(tǒng)下將輸出:
$ g++ t1.cpp -o t1 -std=c++11 -pthread $ ./t2 thread function main thread
我們要做的第一件事是創(chuàng)建一個(gè)線程對(duì)象(工作線程),并給它一個(gè)函數(shù)形式的任務(wù)進(jìn)行工作。
主線程希望等待線程成功完成。
所以,我們使用join(). 如果最初的主線程不等待新線程執(zhí)行完成,那么它會(huì)繼續(xù)執(zhí)行main()函數(shù)之后的代碼,可能在新線程執(zhí)行完畢前結(jié)束程序。
當(dāng)主線程在等待時(shí),主線程處于空閑狀態(tài)。
實(shí)際上,操作系統(tǒng)可能會(huì)把CPU資源從主線程上移走。
請(qǐng)注意,我們?cè)诰€程的函數(shù)和類(lèi)的聲明中有一個(gè)新的標(biāo)準(zhǔn)C++庫(kù)頭文件#include <thread>。
下圖是流程的流程圖

然而,在實(shí)際執(zhí)行中,事情并不是那么理想,更可能是不對(duì)稱的。也許,它看起來(lái)更像下面這張圖片。

當(dāng)工作線程開(kāi)始構(gòu)造std::thread t的時(shí)候,可能會(huì)有創(chuàng)建時(shí)的開(kāi)銷(xiāo)(通過(guò)使用線程池可以減少此開(kāi)銷(xiāo)),圖中虛線表示可能的阻塞狀態(tài)。
線程的分離
我們可以創(chuàng)建一個(gè)新線程使其運(yùn)行為自由的守護(hù)進(jìn)程。
// t2.cpp
int main()
{
std::thread t(&thread;_function);
std::cout << "main thread\n";
// t.join();
t.detach();
return 0;
}
分離的子線程現(xiàn)在是自由的,并自行運(yùn)行。它變成了一個(gè)守護(hù)進(jìn)程。
$ g++ t2.cpp -o t2 -std=c++11 -pthread $ ./t2 main thread
注意,分離線程沒(méi)有改變打印輸出到標(biāo)準(zhǔn)輸出stdout,因?yàn)橹骶€程已經(jīng)結(jié)束并退出。
這是多線程編程的特點(diǎn)之一:我們不能確定哪個(gè)線程首先運(yùn)行 (不確定性,除非我們使用同步機(jī)制。). 在我們的例子中,由于創(chuàng)建一個(gè)新線程需要一定的時(shí)間,主線程最有可能比子線程率先執(zhí)行完畢。
還有一點(diǎn)我們需要注意的是,即使在這個(gè)簡(jiǎn)單的代碼中,我們也在共享一個(gè)公共資源:std::cout。
因此,為了使代碼正常工作,主線程應(yīng)該允許我們的子線程訪問(wèn)資源。
一旦一個(gè)線程分離,我們不能強(qiáng)迫它與主線程重新連接。因此,下面的代碼行是錯(cuò)誤的,程序會(huì)崩潰。
int main()
{
std::thread t(&thread;_function);
std::cout << "main thread\n";
// t.join();
t.detach();
t.join(); // Error
return 0;
}
一旦脫離,線程就應(yīng)該永遠(yuǎn)是脫離狀態(tài).
我們可以使用joinable()把代碼做崩潰前的檢查。
因?yàn)樗黬oinable()返回為false,join()函數(shù)不會(huì)被調(diào)用,程序運(yùn)行不會(huì)崩潰。
int main()
{
std::thread t(&thread;_function);
std::cout << "main thread\n";
// t.join();
if(t.joinable())
t.join();
return 0;
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
實(shí)現(xiàn)C語(yǔ)言常用字符串庫(kù)函數(shù)
這篇文章主要為大家介紹了如何實(shí)現(xiàn)C語(yǔ)言常用字符串庫(kù)函數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2021-11-11
C語(yǔ)言詳細(xì)分析講解內(nèi)存管理malloc realloc free calloc函數(shù)的使用
C語(yǔ)言內(nèi)存管理相關(guān)的函數(shù)主要有realloc、calloc、malloc、free等,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言內(nèi)存管理realloc、calloc、malloc、free函數(shù)的相關(guān)資料,需要的朋友可以參考下2022-05-05
C語(yǔ)言如何在指針中隱藏?cái)?shù)據(jù)詳解
這篇文章主要給大家介紹了關(guān)于C語(yǔ)言如何在指針中隱藏?cái)?shù)據(jù)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧2018-12-12
利用C++實(shí)現(xiàn)從std::string類(lèi)型到bool型的轉(zhuǎn)換
利用C++實(shí)現(xiàn)從std::string類(lèi)型到bool型的轉(zhuǎn)換。需要的朋友可以過(guò)來(lái)參考下。希望對(duì)大家有所幫助2013-10-10
對(duì)一個(gè)數(shù)組進(jìn)行zig-zag重新排列
本文介紹了“對(duì)一個(gè)數(shù)組進(jìn)行zig-zag重新排列”,需要的朋友可以參考一下2013-03-03
深入解析C++11?lambda表達(dá)式/包裝器/線程庫(kù)
這篇文章主要介紹了C++11?lambda表達(dá)式/包裝器/線程庫(kù)的相關(guān)知識(shí),本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05
VS中scanf函數(shù)報(bào)錯(cuò)問(wèn)題的幾種解決方法
本文主要介紹了VS中scanf函數(shù)報(bào)錯(cuò)問(wèn)題的幾種解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
C語(yǔ)言每日練習(xí)之統(tǒng)計(jì)文本單詞數(shù)及高頻詞
本文文大家準(zhǔn)備了個(gè)C語(yǔ)言練習(xí)題:統(tǒng)計(jì)單詞數(shù)并找出頻率最高的單詞,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C語(yǔ)言有一定幫助,感興趣的可以了解一下2022-05-05

