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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++多线程快速入门(一):基本常用操作

發布時間:2023/12/1 c/c++ 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++多线程快速入门(一):基本常用操作 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

    • case1:創建線程1 join、detach
    • case2:創建線程2 線程傳參 傳值或者傳引用
    • case3:創建線程 線程傳參 functional object作為參數
    • case4:觀察多線程程序加速計算
    • case5:future + get 獲取并發結果
    • case6:互斥鎖
    • case7:std::lock_guard 類模板

case1:創建線程1 join、detach

創建線程,并等該線程執行完畢,并且打印兩個線程的id

#include <iostream> #include <thread> using namespace std; void func() {cout << "hello , this is my thread, thread id is " << this_thread::get_id() << endl; } int main() {thread th = thread(func);th.join();cout << "this is main thread and its id is " << this_thread::get_id() << endl; }

執行結果如下:

C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe hello , this is my thread, thread id is 2 this is main thread and its id is 1Process finished with exit code 0

使用detach,放棄對該線程的控制:

#include <iostream> #include <thread>using namespace std;void func() {cout << "hello , this is my thread, thread id is " << this_thread::get_id() << endl; } int main() {thread th = thread(func);th.detach();// 如果我們此時不再關系該線程的運行情況的話可以使用detachcout << th.joinable() << endl;cout << "this is main thread and its id is " << this_thread::get_id() << endl; }

運行結果:

C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe 0 this is main thread and its id is 1 hello , this is my thread, thread id is 2Process finished with exit code 0

case2:創建線程2 線程傳參 傳值或者傳引用

傳值

#include <iostream> #include <thread>using namespace std;void func(string s) {cout << "hello , this is my thread, thread arg is " << s << endl; } int main() {thread th = thread(func, "test");th.join();cout << "this is main thread and its id is " << this_thread::get_id() << endl; }

打印結果如下:

C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe hello , this is my thread, thread arg is test this is main thread and its id is 1Process finished with exit code 0

傳引用

#include <iostream> #include <thread>using namespace std;void func(string& s) {cout << (&s) << endl;cout << "hello , this is my thread, thread arg is " << s << endl; } int main() {string str = "test";thread th = thread(func, ref(str));cout << (&str) << endl;th.join();cout << "this is main thread and its id is " << this_thread::get_id() << endl; }

打印結果如下:

C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe 0x62fd10 0x62fd10 hello , this is my thread, thread arg is test this is main thread and its id is 1Process finished with exit code 0

case3:創建線程 線程傳參 functional object作為參數

關于仿函數的定義可以看:仿函數
如果單純地將邏輯函數傳入thread,在函數邏輯比較復雜的時候不太好。
將函數封裝到類的內部,可以賦予一定的封裝性,并且可以在類內部創建例如map的數據結構來記錄函數運行的狀態。
仿函數、不帶參

#include <iostream> #include <thread>using namespace std;// functional object struct A {void operator()() {cout << "I'm A" << endl;} }; void show() {cout << "I'm show" << endl; } int main() {show();A a;a(); // 等價于 a.operator()();// 我們把這種object稱為callable的object ,又稱為仿函數thread thread1 = thread(A());thread1.join();return 0; }

打印結果如下:

C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe I'm show I'm A I'm AProcess finished with exit code 0

仿函數、帶參

#include <iostream> #include <thread>using namespace std;// functional object struct A {void operator()(int num) {for (int i = 0; i < num; i++) {cout << "I'm A" << i << endl;}} };int main() {int num = 10;thread thread1 = thread(A(), num);for (int i = 0; i < num; i++) {cout << "I'm main" << i << endl;}thread1.join();return 0; }

打印結果如下,是亂序的,符合多線程特性
并且 cout 并不是線程安全的,所以可以發現,有亂碼的樣子

C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe I'm mainI'm A00I'm A1 I'm A2 I'm A3 I'm AI'm main41I'm mainI'm A25I'm mainI'm A36I'm AI'm main47I'm main5 I'm mainI'm A86I'm mainI'm A97I'm main8 I'm main9Process finished with exit code 0

lambda函數作為參數

#include <iostream> #include <thread>using namespace std;int main() {string s = "test";thread f = thread([&s](int a,int b) {cout << s << endl;cout << a + b << endl;}, 2, 3);f.join();return 0; }

打印結果:

C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe test 5Process finished with exit code 0

case4:觀察多線程程序加速計算

#include <iostream> #include <thread>using namespace std;// 測量一個函數的運行時間 template <class T> void measure(T&& func) {using namespace std::chrono;auto start = system_clock::now();// funcfunc();duration<double> diff = system_clock::now() - start;cout << "執行了" << diff.count() << "秒" << endl; }// 求和函數[start,end) void sum(long start, long end, long& ans) {long s = 0;for(auto i = start; i < end; i++) {s += i;}ans = s; }const long S = 100000000;int main() {// 測量一下把工作分攤給兩個線程做的時間measure([](){long ans1, ans2;thread t1 = thread(sum, 0, S >> 1, std::ref(ans1));thread t2 = thread(sum, S >> 1, S, std::ref(ans2));t1.join();t2.join();cout << "ans = " << ans1 + ans2 << endl;});// 測量一下單線程工作時間measure([](){long ans;sum(0, S, ans);cout << "ans = " << ans << endl;});return 0; }

打印結果:

C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe ans = 887459712 執行了0.13546秒 ans = 887459712 執行了0.240006秒Process finished with exit code 0

當然這里有一個細節:
如果在多線程程序中我們傳入了一個ref引用,在線程程序中我們最好不要直接對這個ref值操作,而是采用一個臨時變量,例如上面的程序中我們就使用了一個臨時變量s,對s進行累加后再把值賦給ans。這樣會提高程序運行效率。

case5:future + get 獲取并發結果

future包裹線程運行結果,使用方法如下:
由于我們線程函數的結果是long,所以首先定義future<long>

#include <iostream> #include <thread> #include <future> #include <vector>using namespace std;// 測量一個函數的運行時間 template <class T> void measure(T&& func) {using namespace std::chrono;auto start = system_clock::now();// funcfunc();duration<double> diff = system_clock::now() - start;cout << "執行了" << diff.count() << "秒" << endl; }// 求和函數[start,end) long sum(long start, long end) {long s = 0;for(auto i = start; i < end; i++) {s += i;}return s; }const long S = 100000000;int main() {// 測量一下把工作分攤給 threadNums 個線程做的時間measure([](){const long threadNums = 8;vector<future<long>> vec;vec.reserve(threadNums);for (int i = 0; i < threadNums; i++) {vec.push_back(async(sum, (S / threadNums) * i, (S / threadNums) * (i + 1)));}long ans = 0;// get 阻塞式地拿到并發結果for (int i = 0; i < threadNums; i++) {ans += vec[i].get();}cout << "ans = " << ans << endl;});// 測量一下單線程工作時間measure([](){long ans = sum(0, S);cout << "ans = " << ans << endl;});return 0; }

運行結果如下:

C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe ans = 887459712 執行了0.0521455秒 ans = 887459712 執行了0.250044秒Process finished with exit code 0

case6:互斥鎖

多個線程訪問同一個值并且對其修改,會導致數據競爭。:

#include <iostream> #include <thread> #include <future> #include <vector>using namespace std; // 測量一個函數的運行時間 template <class T> void measure(T&& func) {using namespace std::chrono;auto start = system_clock::now();// funcfunc();duration<double> diff = system_clock::now() - start;cout << "執行了" << diff.count() << "秒" << endl; }std::mutex mtx; // 求和函數 線程安全的 void sum(long& s) {mtx.lock();for (int i = 0; i < 100000; i++) {s++;}mtx.unlock(); }int main() {// 測量一下把工作分攤給 threadNums 個線程做的時間measure([](){vector<thread> v;long s = 0;for (int i = 0; i < 4; i++) {v.emplace_back(std::thread(sum, std::ref(s)));}for (int i = 0; i < 4; i++) {v[i].join();}cout << "ans " << s << endl;});measure([](){long s = 0;for (int i = 0; i < 4; i++) {sum(s);}cout << "ans " << s << endl;});return 0; }

測試結果:

C:\Users\LENOVO\CLionProjects\untitled\cmake-build-debug\untitled.exe ans 400000 執行了0.0141654秒 ans 400000 執行了0.0155926秒Process finished with exit code 0

case7:std::lock_guard 類模板

如果mtx.lock()和mtx.unlock()之間的語句發生了異常,unlock()語句沒有機會執行!
這會導致mtx一直處于鎖著的狀態,其他使用sum函數的線程就會阻塞。
c++庫已經提供了std::lock_guard類模板,構造時自動加鎖,析構時自動解鎖:
將case6的sum函數修改為下面形式即可:

// 求和函數 線程安全的 void sum(long& s) {std:;lock_guard<std::mutex> guard(mtx);// mtx.lock();for (int i = 0; i < 100000; i++) {s++;}// mtx.unlock(); }

如果想自己實現的lock_guard的話也可以:

class mutexLockGuard{ private:std::mutex& mtx; public:explicit mutexLockGuard(std::mutex& mutex) : mtx(mutex){mtx.lock();}~mutexLockGuard() {mtx.unlock();} };

筆記參考:
C++多線程快速入門

總結

以上是生活随笔為你收集整理的C++多线程快速入门(一):基本常用操作的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。