C++多線程編程之創(chuàng)建線程篇
多線程是程序員必須掌握的一門技術(shù),本文主要是針對于C++新標準中多線程庫,需要具備一定C++基礎(chǔ)方可學習。

前言
本章節(jié)主要C++多線程編程中的一些基本概念以及幾種創(chuàng)建線程的方式。
并發(fā)、進程、線程的基本概念
并發(fā)兩個或者多個任務(wù)(獨立的活動)同時發(fā)生(進行):一個程序通知執(zhí)行多個獨立的任務(wù)并發(fā)假象(不是真正的并發(fā)):單核CPU通過上下文切換方式實現(xiàn)進程
進程計算機中的程序關(guān)于某數(shù)據(jù)集合上的一次運行活動
進程特性
- 動態(tài)性:進程是程序的一次執(zhí)行過程,是臨時的,有生命期,是動態(tài)產(chǎn)生,動態(tài)消亡的;
- 并發(fā)性:任何進程都可以同其他進行一起并發(fā)執(zhí)行;
- 獨立性:進程是系統(tǒng)進行資源分配和調(diào)度的一個獨立單位;
- 結(jié)構(gòu)性:進程由程序,數(shù)據(jù)和進程控制塊三部分組成
線程每個進程都有一個主線程并且主線程是唯一的,也就是一個進程只能有一個主線程。vs編譯器中ctr+f5編譯運行程序時,實際是主線程調(diào)用mian函數(shù)中的代碼。線程可以理解為代碼執(zhí)行通道,除了主線程之外,可以自己創(chuàng)建其他線程。
并發(fā)實現(xiàn)方案
主要解決是進程間通信問題
同一電腦上可通過管道,文件,消息隊列,共享內(nèi)存等方式實現(xiàn)
不同電腦可通過socket網(wǎng)絡(luò)通信實現(xiàn)
多個進程實現(xiàn)并發(fā)
單獨進程,多個線程實現(xiàn)并發(fā) 即一個主線程,多個子線程實現(xiàn)并發(fā)一個進程中的所有線程共享內(nèi)存空間(共享內(nèi)存),例如全局變量,指針引用等,所以多線程開銷遠遠小于多進程。共享內(nèi)存也會導(dǎo)致數(shù)據(jù)一致性問題(資源競爭問題)。
C++線程編程基本操作
1.首先需要包含thread頭文件
- #include <thread>
- #include <iostream>
2.創(chuàng)建線程: thread類創(chuàng)建一個線程
- #include <thread>
- void print()
- {
- std::cout<<"子線程"<<endl;
- }
- int main()
- {
- //運行程序會調(diào)用abort函數(shù)終止程序
- std::thread t1(print);
- std::cout<<"主線程"<<std::endl;
- }
3.join:加入/匯合線程。阻塞主線程,等待子線程執(zhí)行結(jié)束,可理解為依附功能
- #include <thread>
- void print()
- {
- std::cout<<"子線程"<<endl;
- }
- int main()
- {
- std::thread t1(print);
- t1.join(); //阻塞主線程,等待子線程執(zhí)行結(jié)束
- std::cout<<"主線程"<<std::endl;
- return 0;
- }
4.detach:分離,剝離依附關(guān)系,駐留后臺
- #include <thread>
- #include <iostream>
- #include <windows.h>
- void print()
- {
- for (int i = 0; i < 10; i++)
- {
- std::cout << "子線程"<<i << std::endl;
- }
- }
- int main()
- {
- std::thread t1(print);
- std::cout << "主線程" << std::endl;
- //可用Sleep延時實現(xiàn)結(jié)果演示
- t1.detach();
- return 0;
- }
注意:一旦detach線程后,便不可再使用join線程。
5.joinable:判斷當前線程是否可以join或deatch,如果可以返回true,不能返回false
- #include <thread>
- #include <iostream>
- void print()
- {
- for (int i = 0; i < 10; i++)
- {
- std::cout << "子線程"<<i << std::endl;
- }
- }
- int main()
- {
- std::thread t1(print);
- t1.detach();
- if (t1.joinable())
- {
- t1.join();
- std::cout << "可join" << std::endl;
- }
- std::cout << "主線程" << std::endl;
- return 0;
- }
其他創(chuàng)建線程方法
1.用類和對象
- #include <thread>
- #include <iostream>
- class Function
- {
- public:
- void operator()()
- {
- std::cout << "子線程" << std::endl;
- }
- };
- int main()
- {
- Function object;
- std::thread t1(object); //可調(diào)用對象即可
- t1.join();
- std::thread t2((Function()));
- t2.join();
- std::cout << "主線程" << std::endl;
- return 0;
- }
2.Lambda表達式
- #include <thread>
- #include <iostream>
- int main()
- {
- std::thread t1([] {std::cout << "子線程" << std::endl; });
- t1.join();
- std::cout << "主線程" << std::endl;
- return 0;
- }
3.帶引用參數(shù)創(chuàng)建方式
- #include <thread>
- #include <iostream>
- #include <thread>
- void printInfo(int& num)
- {
- num = 1001;
- std::cout << "子進程:"<<num << std::endl;
- }
- int main()
- {
- int num = 0;
- //std::ref 用于包裝按引用傳遞的值。
- //std::cref 用于包裝按const引用傳遞的值
- //error C2672: “invoke”: 未找到匹配的重載函數(shù)
- std::thread t(printInfo, std::ref(num));
- t.join();
- std::cout << "主線程:"<<num << std::endl;
- return 0;
- }
4.帶智能指針參數(shù)創(chuàng)建方式
- #include <thread>
- #include <iostream>
- #include <thread>
- void printInfo(std::unique_ptr<int> ptr)
- {
- std::cout << "子線程:"<<ptr.get() << std::endl;
- }
- int main()
- {
- std::unique_ptr<int> ptr(new int(100));
- std::cout << "主線程:" << ptr.get() << std::endl;
- std::thread t(printInfo,std::move(ptr));
- t.join();
- std::cout << "主線程:"<<ptr.get() << std::endl; //主線程:00000000 move掉了
- return 0;
- }
5.類的成員函數(shù)
- #include <thread>
- #include <iostream>
- #include <thread>
- class MM
- {
- public:
- void print(int& num)
- {
- num = 1001;
- std::cout << "子線程:"<<num << std::endl;
- }
- };
- int main()
- {
- MM mm;
- int num = 10;
- std::thread t(&MM::print,mm,std::ref(num));
- t.join();
- std::cout << "主線程:"<< num << std::endl;
- return 0;
- }
好了,創(chuàng)建線程就介紹到這里,大家可以先練習一下,下章節(jié)講解共享數(shù)據(jù)訪問。