C++11并发之std::thread
生活随笔
收集整理的這篇文章主要介紹了
C++11并发之std::thread
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
C++11并發(fā)之std::thread 知識鏈接: C++11 并發(fā)之std::mutex C++11 并發(fā)之std::atomic 本文概要: 1、成員類型和成員函數(shù)。 2、std::thread 構(gòu)造函數(shù)。 3、異步。 4、多線程傳遞參數(shù)。 5、join、detach。 6、獲取CPU核心個數(shù)。 7、CPP原子變量與線程安全。 8、lambda與多線程。 9、時間等待相關(guān)問題。 10、線程功能拓展。 11、多線程可變參數(shù)。 12、線程交換。 13、線程移動。 std::thread 在 #include<thread> 頭文件中聲明,因此使用 std::thread 時需要包含?#include<thread>?頭文件。 1、成員類型和成員函數(shù)。 成員類型: idThread id?(public member type ) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id native_handle_typeNative handle type?(public member type ) Construct thread?(public member function ) ? ? ? ?構(gòu)造函數(shù) (destructor)Thread destructor?(public member function ) ? ? ?析構(gòu)函數(shù) operator=Move-assign thread?(public member function ) ?賦值重載 get_idGet thread id?(public member function ) ? ? ? ? ? ? ? ?獲取線程id joinableCheck if joinable?(public member function ) ? ? ? ? ?判斷線程是否可以加入等待 joinJoin thread?(public member function ) ? ? ? ? ? ? ? ? ? ?加入等待 detachDetach thread?(public member function ) ? ? ? ? ? ? ?分離線程 swapSwap threads?(public member function ) ? ? ? ? ? ? ? 線程交換 native_handleGet native handle?(public member function ) ? ? ? 獲取線程句柄 hardware_concurrency [static]Detect hardware concurrency?(public static member function ) ? 檢測硬件并發(fā)特性 Swap threads?(function ) 2、std::thread 構(gòu)造函數(shù)。 如下表: default (1)thread() noexcept; initialization(2)template <class Fn, class... Args> ? explicit thread (Fn&& fn, Args&&... args); copy [deleted] (3)thread (const thread&) = delete; move [4]hread (thread&& x) noexcept; (1).默認(rèn)構(gòu)造函數(shù),創(chuàng)建一個空的 thread 執(zhí)行對象。 (2).初始化構(gòu)造函數(shù),創(chuàng)建一個 thread 對象,該 thread 對象可被 joinable,新產(chǎn)生的線程會調(diào)用 fn 函數(shù),該函數(shù)的參數(shù)由 args 給出。 (3).拷貝構(gòu)造函數(shù)(被禁用),意味著 thread 不可被拷貝構(gòu)造。 (4).move 構(gòu)造函數(shù),move 構(gòu)造函數(shù),調(diào)用成功之后 x 不代表任何 thread 執(zhí)行對象。 注意:可被 joinable 的 thread 對象必須在他們銷毀之前被主線程 join 或者將其設(shè)置為 detached。 std::thread 各種構(gòu)造函數(shù)例子如下: [cpp]?view plain?copy <span?style="font-size:12px;">#include<iostream>?? #include<thread>?? #include<chrono>?? using?namespace?std;?? void?fun1(int?n)??//初始化構(gòu)造函數(shù)?? {?? ????cout?<<?"Thread?"?<<?n?<<?"?executing\n";?? ????n?+=?10;?? ????this_thread::sleep_for(chrono::milliseconds(10));?? }?? void?fun2(int?&?n)?//拷貝構(gòu)造函數(shù)?? {?? ????cout?<<?"Thread?"?<<?n?<<?"?executing\n";?? ????n?+=?20;?? ????this_thread::sleep_for(chrono::milliseconds(10));?? }?? int?main()?? {?? ????int?n?=?0;?? ????thread?t1;???????????????//t1不是一個thread?? ????thread?t2(fun1,?n?+?1);??//按照值傳遞?? ????t2.join();?? ????cout?<<?"n="?<<?n?<<?'\n';?? ????n?=?10;?? ????thread?t3(fun2,?ref(n));?//引用?? ????thread?t4(move(t3));?????//t4執(zhí)行t3,t3不是thread?? ????t4.join();?? ????cout?<<?"n="?<<?n?<<?'\n';?? ????return?0;?? }?? 運行結(jié)果:?? Thread?1?executing?? n=0?? Thread?10?executing?? n=30</span>?? 3、異步。 例如: [cpp]?view plain?copy <span?style="font-size:12px;">#include<iostream>?? #include<thread>?? using?namespace?std;?? void?show()?? {?? ????cout?<<?"hello?cplusplus!"?<<?endl;?? }?? int?main()?? {?? ????//棧上?? ????thread?t1(show);???//根據(jù)函數(shù)初始化執(zhí)行?? ????thread?t2(show);?? ????thread?t3(show);?? ????//線程數(shù)組?? ????thread?th[3]{thread(show),?thread(show),?thread(show)};??? ????//堆上?? ????thread?*pt1(new?thread(show));?? ????thread?*pt2(new?thread(show));?? ????thread?*pt3(new?thread(show));?? ????//線程指針數(shù)組?? ????thread?*pth(new?thread[3]{thread(show),?thread(show),?thread(show)});?? ????return?0;?? }</span>?? 4、多線程傳遞參數(shù)。 例如: [cpp]?view plain?copy <span?style="font-size:12px;">#include<iostream>?? #include<thread>?? using?namespace?std;?? void?show(const?char?*str,?const?int?id)?? {?? ????cout?<<?"線程?"?<<?id?+?1?<<?"?:"?<<?str?<<?endl;?? }?? int?main()?? {?? ????thread?t1(show,?"hello?cplusplus!",?0);?? ????thread?t2(show,?"你好,C++!",?1);?? ????thread?t3(show,?"hello!",?2);?? ????return?0;?? }?? 運行結(jié)果:?? 線程?1線程?2?:你好,C++!線程?3?:hello!?? :hello?cplusplus!</span>?? 發(fā)現(xiàn),線程 t1、t2、t3 都執(zhí)行成功! 5、join、detach。 join例子如下: [cpp]?view plain?copy <span?style="font-size:12px;">#include<iostream>?? #include<thread>?? #include<array>?? using?namespace?std;?? void?show()?? {?? ????cout?<<?"hello?cplusplus!"?<<?endl;?? }?? int?main()?? {?? ????array<thread,?3>??threads?=?{?thread(show),?thread(show),?thread(show)?};?? ????for?(int?i?=?0;?i?<?3;?i++)?? ????{?? ????????cout?<<?threads[i].joinable()?<<?endl;//判斷線程是否可以join?? ????????threads[i].join();//主線程等待當(dāng)前線程執(zhí)行完成再退出?? ????}?? ????return?0;?? }?? 運行結(jié)果:?? hello?cplusplus!?? hello?cplusplus!?? 1?? hello?cplusplus!?? 1?? 1</span>?? 總結(jié): join 是讓當(dāng)前主線程等待所有的子線程執(zhí)行完,才能退出。 detach例子如下: [cpp]?view plain?copy <span?style="font-size:12px;">#include<iostream>?? #include<thread>?? using?namespace?std;?? void?show()?? {?? ????cout?<<?"hello?cplusplus!"?<<?endl;?? }?? int?main()?? {?? ????thread?th(show);?? ????//th.join();??? ????th.detach();//脫離主線程的綁定,主線程掛了,子線程不報錯,子線程執(zhí)行完自動退出。?? ????//detach以后,子線程會成為孤兒線程,線程之間將無法通信。?? ????cout?<<?th.joinable()?<<?endl;?? ????return?0;?? }?? 運行結(jié)果:?? hello?cplusplus!?? 0</span>?? 結(jié)論: 線程 detach 脫離主線程的綁定,主線程掛了,子線程不報錯,子線程執(zhí)行完自動退出。 線程 detach以后,子線程會成為孤兒線程,線程之間將無法通信。 6、獲取CPU核心個數(shù)。 例如: [cpp]?view plain?copy <span?style="font-size:12px;">#include<iostream>?? #include<thread>?? using?namespace?std;?? int?main()?? {?? ????auto?n?=?thread::hardware_concurrency();//獲取cpu核心個數(shù)?? ????cout?<<?n?<<?endl;?? ????return?0;?? }?? 運行結(jié)果:?? 8</span>?? 結(jié)論: 通過 ?thread::hardware_concurrency() 獲取 CPU 核心的個數(shù)。 7、CPP原子變量與線程安全。 問題例如: [cpp]?view plain?copy <span?style="font-size:12px;">#include<iostream>?? #include<thread>?? using?namespace?std;?? const?int?N?=?100000000;?? int?num?=?0;?? void?run()?? {?? ????for?(int?i?=?0;?i?<?N;?i++)?? ????{?? ????????num++;?? ????}?? }?? int?main()?? {?? ????clock_t?start?=?clock();?? ????thread?t1(run);?? ????thread?t2(run);?? ????t1.join();?? ????t2.join();?? ????clock_t?end?=?clock();?? ????cout?<<?"num="?<<?num?<<?",用時?"?<<?end?-?start?<<?"?ms"?<<?endl;?? ????return?0;?? }?? 運行結(jié)果:?? num=143653419,用時?730?ms</span>?? 從上述代碼執(zhí)行的結(jié)果,發(fā)現(xiàn)結(jié)果并不是我們預(yù)計的200000000,這是由于線程之間發(fā)生沖突,從而導(dǎo)致結(jié)果不正確。 為了解決此問題,有以下方法: (1)互斥量。 例如: [cpp]?view plain?copy <span?style="font-size:12px;">#include<iostream>?? #include<thread>?? #include<mutex>?? using?namespace?std;?? const?int?N?=?100000000;?? int?num(0);?? mutex?m;?? void?run()?? {?? ????for?(int?i?=?0;?i?<?N;?i++)?? ????{?? ????????m.lock();?? ????????num++;?? ????????m.unlock();?? ????}?? }?? int?main()?? {?? ????clock_t?start?=?clock();?? ????thread?t1(run);?? ????thread?t2(run);?? ????t1.join();?? ????t2.join();?? ????clock_t?end?=?clock();?? ????cout?<<?"num="?<<?num?<<?",用時?"?<<?end?-?start?<<?"?ms"?<<?endl;?? ????return?0;?? }?? 運行結(jié)果:?? num=200000000,用時?128323?ms</span>?? 不難發(fā)現(xiàn),通過互斥量后運算結(jié)果正確,但是計算速度很慢,原因主要是互斥量加解鎖需要時間。 互斥量詳細內(nèi)容?請參考C++11 并發(fā)之std::mutex。 (2)原子變量。 例如: [cpp]?view plain?copy <span?style="font-size:12px;">#include<iostream>?? #include<thread>?? #include<atomic>?? using?namespace?std;?? const?int?N?=?100000000;?? atomic_int?num{?0?};//不會發(fā)生線程沖突,線程安全?? void?run()?? {?? ????for?(int?i?=?0;?i?<?N;?i++)?? ????{?? ????????num++;?? ????}?? }?? int?main()?? {?? ????clock_t?start?=?clock();?? ????thread?t1(run);?? ????thread?t2(run);?? ????t1.join();?? ????t2.join();?? ????clock_t?end?=?clock();?? ????cout?<<?"num="?<<?num?<<?",用時?"?<<?end?-?start?<<?"?ms"?<<?endl;?? ????return?0;?? }?? 運行結(jié)果:?? num=200000000,用時?29732?ms</span>?? 不難發(fā)現(xiàn),通過原子變量后運算結(jié)果正確,計算速度一般。 原子變量詳細內(nèi)容?請參考C++11 并發(fā)之std::atomic。 (3)加入 join 。 例如: [cpp]?view plain?copy <span?style="font-size:12px;">#include<iostream>?? #include<thread>?? using?namespace?std;?? const?int?N?=?100000000;?? int?num?=?0;?? void?run()?? {?? ????for?(int?i?=?0;?i?<?N;?i++)?? ????{?? ????????num++;?? ????}?? }?? int?main()?? {?? ????clock_t?start?=?clock();?? ????thread?t1(run);?? ????t1.join();?? ????thread?t2(run);?? ????t2.join();?? ????clock_t?end?=?clock();?? ????cout?<<?"num="?<<?num?<<?",用時?"?<<?end?-?start?<<?"?ms"?<<?endl;?? ????return?0;?? }?? 運行結(jié)果:?? num=200000000,用時?626?ms</span>?? 不難發(fā)現(xiàn),通過原子變量后運算結(jié)果正確,計算速度也很理想。 8、lambda與多線程。 例如: [cpp]?view plain?copy <span?style="font-size:12px;">#include<iostream>?? #include<thread>?? using?namespace?std;?? int?main()?? {?? ????auto?fun?=?[](const?char?*str)?{cout?<<?str?<<?endl;?};?? ????thread?t1(fun,?"hello?world!");?? ????thread?t2(fun,?"hello?beijing!");?? ????return?0;?? }?? 運行結(jié)果:?? hello?world!?? hello?beijing!</span>?? 9、時間等待相關(guān)問題。 例如: [cpp]?view plain?copy <span?style="font-size:12px;">#include<iostream>?? #include<thread>?? #include<chrono>?? using?namespace?std;?? int?main()?? {?? ????thread?th1([]()?? ????{?? ????????//讓線程等待3秒?? ????????this_thread::sleep_for(chrono::seconds(3));?? ????????//讓cpu執(zhí)行其他空閑的線程?? ????????this_thread::yield();?? ????????//線程id?? ????????cout?<<?this_thread::get_id()?<<?endl;?? ????});?? ????return?0;?? }</span>?? 10、線程功能拓展。 例如: [cpp]?view plain?copy <span?style="font-size:12px;">#include<iostream>?? #include<thread>?? using?namespace?std;?? class?MyThread?:public?thread???//繼承thread?? {?? public:?? ????//子類MyThread()繼承thread()的構(gòu)造函數(shù)?? ????MyThread()?:?thread()?? ????{?? ????}?? ????//MyThread()初始化構(gòu)造函數(shù)?? ????template<typename?T,?typename...Args>?? ????MyThread(T&&func,?Args&&...args)?:?thread(forward<T>(func),?forward<Args>(args)...)?? ????{?? ????}?? ????void?showcmd(const?char?*str)??//運行system?? ????{?? ????????system(str);?? ????}?? };?? int?main()?? {?? ????MyThread?th1([]()?? ????{?? ????????cout?<<?"hello"?<<?endl;?? ????});?? ????th1.showcmd("calc");?//運行calc?? ????//lambda?? ????MyThread?th2([](const?char?*?str)?? ????{?? ????????cout?<<?"hello"?<<?str?<<?endl;?? ????},?"?this?is?MyThread");?? ????th2.showcmd("notepad");//運行notepad?? ????return?0;?? }?? 運行結(jié)果:?? hello?? //運行calc?? hello?this?is?MyThread?? //運行notepad</span>?? 11、多線程可變參數(shù)。 例如: [cpp]?view plain?copy <span?style="font-size:12px;">#include<iostream>?? #include<thread>?? #include<cstdarg>?? using?namespace?std;?? int?show(const?char?*fun,?...)?? {?? ????va_list?ap;//指針?? ????va_start(ap,?fun);//開始?? ????vprintf(fun,?ap);//調(diào)用?? ????va_end(ap);?? ????return?0;?? }?? int?main()?? {?? ????thread?t1(show,?"%s????%d????%c????%f",?"hello?world!",?100,?'A',?3.14159);?? ????return?0;?? }?? 運行結(jié)果:?? hello?world!????100????A????3.14159</span>?? 12、線程交換。 例如: [cpp]?view plain?copy <span?style="font-size:12px;">#include<iostream>?? #include<thread>?? using?namespace?std;?? int?main()?? {?? ????thread?t1([]()?? ????{?? ????????cout?<<?"thread1"?<<?endl;?? ????});?? ????thread?t2([]()?? ????{?? ????????cout?<<?"thread2"?<<?endl;?? ????});?? ????cout?<<?"thread1'?id?is?"?<<?t1.get_id()?<<?endl;?? ????cout?<<?"thread2'?id?is?"?<<?t2.get_id()?<<?endl;?? ?????? ????cout?<<?"swap?after:"?<<?endl;?? ????swap(t1,?t2);//線程交換?? ????cout?<<?"thread1'?id?is?"?<<?t1.get_id()?<<?endl;?? ????cout?<<?"thread2'?id?is?"?<<?t2.get_id()?<<?endl;?? ????return?0;?? }?? 運行結(jié)果:?? thread1?? thread2?? thread1'?id?is?4836?? thread2'?id?is?4724?? swap?after:?? thread1'?id?is?4724?? thread2'?id?is?4836</span>?? 兩個線程通過 swap 進行交換。 13、線程移動。 例如: [cpp]?view plain?copy <span?style="font-size:12px;">#include<iostream>?? #include<thread>?? using?namespace?std;?? int?main()?? {?? ????thread?t1([]()?? ????{?? ????????cout?<<?"thread1"?<<?endl;?? ????});?? ????cout?<<?"thread1'?id?is?"?<<?t1.get_id()?<<?endl;?? ????thread?t2?=?move(t1);;?? ????cout?<<?"thread2'?id?is?"?<<?t2.get_id()?<<?endl;?? ????return?0;?? }?? 運行結(jié)果:?? thread1?? thread1'?id?is?5620?? thread2'?id?is?5620</span>?? 從上述代碼中,線程t2可以通過 move 移動 t1 來獲取 t1 的全部屬性,而 t1 卻銷毀了。
成員函數(shù):
(constructor)Non-member overloads:
swap (thread)轉(zhuǎn)載于:https://www.cnblogs.com/mmc9527/p/10427924.html
總結(jié)
以上是生活随笔為你收集整理的C++11并发之std::thread的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IDEA 和 Eclipse 集成开发工
- 下一篇: 提取字典的子集