C++中std::thread線程用法
1:std::thread的基本用法
最簡單的 std::thread用法如下,調(diào)用 thread將立即同時(shí)開始執(zhí)行這個(gè)新建立的線程,新線程的任務(wù)執(zhí)行完畢之后, main()的主線程也會(huì)繼續(xù)執(zhí)行。
#include<iostream> #include<thread> #include<windows.h> #include<string> using namespace std; void myfunc_work() { cout << "myfunc_work ....." << endl; // do something 5s Sleep(5000); } int main() { std::thread t1(myfunc_work); // 阻塞當(dāng)前main主線程,待子線程執(zhí)行完畢后,自己恢復(fù)主線程邏輯 t1.join(); cout << "main thread ....." << endl; }
2:std:: thread常用的成員函數(shù)
下面為C++ std::thread常用的成員函數(shù)
get_id() 取得目前的線程 id, 回傳一個(gè) std::thread::id 類型
joinable() 檢查是否可 join
join() // 阻塞當(dāng)前線程,等待子線程執(zhí)行完畢
detach() // 與該線程分離,一旦該線程執(zhí)行完后它所分配的資源就會(huì)被釋放
native_handle() 取得平臺(tái)原生的 native handle.
sleep_for() // 停止目前線程一段指定的時(shí)間
yield() // 暫時(shí)放棄CPU一段時(shí)間,讓給其他線程
void foo() { cout << "foo\n"; } void bar(int x) { cout << "bar\n"; } int main() { //std::thread t1(myfunc_work); //cout << "main thread ....." << endl; 阻塞當(dāng)前main主線程,待子線程執(zhí)行完畢后,自己恢復(fù)主線程邏輯 //t1.join(); thread t1(foo); thread t2(bar, 10); cout << "main,foo,bar execute concurrently....\n"; cout << "sleep 1s\n"; this_thread::sleep_for(chrono::seconds(2)); cout << "join t1\n"; t1.join(); cout << "join t2\n"; t2.join(); cout << "foo and bar thread complete"; }
很顯然:新線程建立后,是否立即執(zhí)行新線程業(yè)務(wù)代碼,有一定的隨機(jī)性。
但是我們可以通過 thread.join() 或者 sleep_for() 來控制代碼執(zhí)行順序
3:建立新 thread執(zhí)行類別中的函數(shù)
C++ std::thread 的構(gòu)建可以傳入class類別中的成員函數(shù),如下范例所示:AA::start 分別建立t1, t2 兩個(gè)線程,而 t1傳入 AA::a1 類別函數(shù)。
notice :
第一個(gè)參數(shù):AA::a1 前面需要添加 &
第二個(gè)參數(shù):代表的是那個(gè)類對(duì)象
后面參數(shù): 按照要求傳入即可
class AA { public: void a1() { cout << "a1\n"; } void a2(int n) { cout << "a2 : " << n << "\n"; } void start() { thread t1(&AA::a1, this); thread t2(&AA::a2, this,10); t1.join(); t2.join(); } private: };
4:建立新 thread 執(zhí)行 lambda expression
std:: thread 的構(gòu)建也可以傳入 lambda expression 表達(dá)式,如下范例:
5:join等待thread執(zhí)行結(jié)束
在main主線程建立 t1線程后,主線程便繼續(xù)往下執(zhí)行,如果主線程需要等待 t1執(zhí)行完畢后才能繼續(xù)執(zhí)行的話,就需要使用 join 。
等待 t1線程執(zhí)行完 foo 后主線程才能繼續(xù)執(zhí)行,如果 t1線程沒有執(zhí)行完,主線程會(huì)一致阻塞在 join這一行。
void test2() { cout << "foo begin...." << endl; this_thread::sleep_for(chrono::milliseconds(5000)); cout << "foo end...." << endl; } int main() { std::thread t1(test2); cout << "main 1....." << endl;; t1.join(); cout << "main 2....."; cout << "main thread run over" << endl; }
6:detach不等待 thread執(zhí)行結(jié)束
承上例:如果主線程不想等或者可以不用等待 t1線程,可以使用 detach來讓 t1線程分離,接著主線程就可以繼續(xù)執(zhí)行,t1線程 也在繼續(xù)執(zhí)行。
/** join等待thread執(zhí)行結(jié)束 */ void test2() { cout << "foo begin...." << endl; this_thread::sleep_for(chrono::milliseconds(50)); cout << "foo end...." << endl; } int main() { std::thread t1(test2); cout << "main 1....." << endl;; t1.detach(); cout << "main 2....."<< endl; cout << "main thread run over" << endl; Sleep(2000); return 0; }
7:std::thread 參數(shù)傳遞使用引用的方法
定義方法:
void? myFunc(int&? n) { ? ? ? ? std::cout << "myFunc? n = " << n << endl; ? ? ? ? n+= 10; }
使用參數(shù)傳遞使用引用目的是: 希望建立另外一個(gè)線程去執(zhí)行 myFunc , 之后需要取得這個(gè) myFunc的運(yùn)算結(jié)果,但是建立線程如果寫: std::thread t1(myFunc , n) 這樣會(huì)編譯出錯(cuò)。
因?yàn)樵?std::thread 的參數(shù)傳遞方式為值傳遞,值傳遞是不可修改的左值,如果要讓其能修改,可以考慮通過 : std::ref 來達(dá)成。
void myFunc(int n) { std::cout << "myFunc n = " << n << endl; n += 10; } void myFunc_ref(int& n) { std::cout << "myFunc reference n = " << n << endl; n += 10; } int main() { int n1 = 5; thread t1(myFunc, n1); t1.join(); cout << "main n1 = " << n1 << "\n"; int n2 = 10; thread t2(myFunc_ref, std::ref(n2)); t2.join(); cout << "main n2 = " << n2 << "\n"; cout << "main thread run over" << endl; return 0; }
到此這篇關(guān)于C++中std::thread線程用法的文章就介紹到這了,更多相關(guān)C++ std::thread線程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C/C++實(shí)現(xiàn)獲取硬盤序列號(hào)的示例代碼
獲取硬盤的序列號(hào)、型號(hào)和固件版本號(hào),此類功能通常用于做硬盤綁定或硬件驗(yàn)證操作,下面我們就來學(xué)習(xí)一下如何使用C/C++實(shí)現(xiàn)獲取硬盤序列號(hào)吧2023-11-11C++中memcpy函數(shù)的使用以及模擬實(shí)現(xiàn)
memcpy是c和c++使用的內(nèi)存拷貝函數(shù),本文主要介紹了C++中memcpy函數(shù)的使用以及模擬實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07Linux中使用VS Code編譯調(diào)試C++項(xiàng)目詳解
最近因?yàn)轫?xiàng)目的需求,需要在Linux下開發(fā)C++相關(guān)項(xiàng)目,經(jīng)過一番摸索最終實(shí)現(xiàn)了,下面這篇文章就給大家簡單總結(jié)了一下如何通過VS Code進(jìn)行編譯調(diào)試的一些注意事項(xiàng)。有需要的朋友們可以參考借鑒,下面來跟著小編一起看看吧。2016-12-12MFC實(shí)現(xiàn)對(duì)話框編輯控件上拖拽文件
這篇文章主要為大家詳細(xì)介紹了MFC實(shí)現(xiàn)對(duì)話框編輯控件上拖拽文件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06C++11中初始化列表initializer lists的使用方法
C++11引入了初始化列表來初始化變量和對(duì)象,自定義類型,如果想用初始化列表就要包含initializer_list頭文件2021-09-09