日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++11并发之std::thread

發(fā)布時間:2023/12/10 c/c++ 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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ù)。 成員類型: id
Thread id?(public member type ) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? id
native_handle_type
Native handle type?(public member type )

成員函數(shù):

(constructor)
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_id
Get thread id?(public member function ) ? ? ? ? ? ? ? ?獲取線程id
joinable
Check if joinable?(public member function ) ? ? ? ? ?判斷線程是否可以加入等待
join
Join thread?(public member function ) ? ? ? ? ? ? ? ? ? ?加入等待
detach
Detach thread?(public member function ) ? ? ? ? ? ? ?分離線程
swap
Swap threads?(public member function ) ? ? ? ? ? ? ? 線程交換
native_handle
Get native handle?(public member function ) ? ? ? 獲取線程句柄
hardware_concurrency [static]
Detect hardware concurrency?(public static member function ) ? 檢測硬件并發(fā)特性

Non-member overloads:

swap (thread)
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).默認構(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 卻銷毀了。

    轉(zhuǎn)載于:https://www.cnblogs.com/mmc9527/p/10427924.html

    總結(jié)

    以上是生活随笔為你收集整理的C++11并发之std::thread的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。