C11 多线程初学1
C++ 11 多線程編程
- 1、線程的創(chuàng)建和使用
- 1.1 創(chuàng)建線程
- 1.2 線程的使用
- 2.實(shí)現(xiàn)線程同步
- 2.1互斥鎖
- 2.2 條件變量
- 3.例
- 1:兩線程交替打印奇偶數(shù)
1、線程的創(chuàng)建和使用
引入線程庫<thread>,其提供了thread類,創(chuàng)建一個(gè)線程即實(shí)例化一個(gè)該類的對(duì)象,以此進(jìn)行線程的創(chuàng)建和使用。
#include<thread> using namespce std;1.1 創(chuàng)建線程
一個(gè)線程可以用一個(gè) thread 類的對(duì)象來表示,thread類中重載了構(gòu)造函數(shù)和移動(dòng)拷貝構(gòu)造
#include<iostream> #include<thread>using namespace std;void funa() {cout << "thread_funa()" << endl; } int main() {//創(chuàng)建線程——構(gòu)造函數(shù)thread a(funa);cout << a.get_id() << endl;//移動(dòng)拷貝構(gòu)造thread b(std::move(a));cout << b.get_id() << endl;b.join();//移動(dòng)拷貝構(gòu)造進(jìn)行資源的交換,所有要注釋掉//a.join();cout << "main end" << endl;}注意: thread類無拷貝構(gòu)造函數(shù)、無賦值運(yùn)算符,即不能直接用一個(gè)事先定義好的thread對(duì)象拷貝構(gòu)造另一個(gè)thread對(duì)象,也不能不能進(jìn)行賦值操作。但可以將臨時(shí)的thread對(duì)象賦值給另一個(gè)thread即移動(dòng)拷貝構(gòu)造,也可以移動(dòng)賦值。
1.2 線程的使用
thread 提供的函數(shù): 線程支持庫
thread類常用的成員函數(shù):
| get_id() | 獲取當(dāng)前thread對(duì)象的線程id |
| joinable() | 判斷當(dāng)前線程是否活躍(是:true;否:false)即是否支持調(diào)用 join() |
| join() | 阻塞當(dāng)前thread 對(duì)象所在的線程,直至thread 對(duì)象表示的線程執(zhí)行完畢 |
| detach() | 將當(dāng)前線程從調(diào)用該函數(shù)的線程中分離出去,他們彼此獨(dú)立運(yùn)行 |
| swap() | 交換兩個(gè)線程的狀態(tài) |
注意:每個(gè)thread 對(duì)象在調(diào)用析構(gòu)銷毀前,要么調(diào)用 join() 函數(shù)令主線程等待子線程執(zhí)行完畢,要么調(diào)用detach() 函數(shù)將子線程和主線程分離,二者必選一,否則存在以下問題:
- 線程占用的資源無法全部釋放,造成內(nèi)存泄露
- 當(dāng)主線程執(zhí)行完畢而子線程未完時(shí),程序執(zhí)行引發(fā)異常。
在this_thread 命名空間的部分函數(shù):
| get_id() | 獲得當(dāng)前線程的 ID |
| yield() | 阻塞當(dāng)前線程讓出cpu,直至條件成熟 |
| sleep_for() | 阻塞當(dāng)前線程指定的時(shí)間 |
| sleep_until() | 阻塞當(dāng)前線程,直至某個(gè)時(shí)間點(diǎn)為止 |
例:
//休眠1000毫秒,1s this_thread::sleep_for(chrono::milliseconds(1000));2.實(shí)現(xiàn)線程同步
2.1互斥鎖
互斥鎖用 mutex 類(位于std命名空間中)的對(duì)象表示,定義在頭文件<mutex>頭文件中。
成員函數(shù):lock()——加鎖; unlock()——解鎖
例:對(duì)臨界資源變量n的訪問
實(shí)現(xiàn)嚴(yán)格基于作用域的互斥體所有權(quán)包裝器:lock_fuard
原理:創(chuàng)建 lock_guard 對(duì)象時(shí),它試圖接收給定互斥的所有權(quán)。控制離開創(chuàng)建 lock_guard 對(duì)象的作用域時(shí),銷毀 lock_guard 并釋放互斥。即,創(chuàng)建即加鎖,作用域結(jié)束自動(dòng)解鎖。
lock_gurad傳入兩個(gè)參數(shù),第二個(gè)為adopt_lock標(biāo)識(shí)時(shí),表示該互斥量之前必須已經(jīng)lock,才能使用此參數(shù),故需要提前手動(dòng)鎖定。
#include<mutex> using namespcase std; mutex m; //實(shí)例化mutex對(duì)象m void Show_n() {m.lock(); //手動(dòng)鎖定lock_guard<mutex> g1(m, adopt_lock);cout << n << endl; } //作用域結(jié)束,析構(gòu)g1,m解鎖實(shí)現(xiàn)可移動(dòng)的互斥體所有權(quán)包裝器:unique_lock
與lock_guard類似,用法更豐富。
| lock() | 鎖定 |
| try_lock() | 嘗試鎖定,若不能,先去執(zhí)行其他代碼并返回false;可以,進(jìn)行加鎖并返回true |
| unlock() | 解鎖 |
unique_lock與lock_guard
| 手動(dòng)lock、unlock | 支持 | 不支持 |
| 參數(shù) | 支持 adopt_lock/try_to_lock/defer_lock | 支持 adopt_lock |
try_to_lock: 嘗試用mutx的lock()去鎖定這個(gè)mutex,但如果沒有鎖定成功,會(huì)立即返回,不會(huì)阻塞在那里
defer_lock: 這個(gè)參數(shù)表示暫時(shí)先不lock,之后手動(dòng)去lock,但是使用之前也是不允許去lock。
2.2 條件變量
C11提供的兩種表示條件變量的類:
都定義在<condition_variable>頭文件中,常與互斥鎖搭配使用,避免線程間搶奪資源。
- condition_variable
該類表示的條件變量只能和unique_lock類表示的互斥鎖搭配使用; - condition_variable_any
該類表示的條件變量可以與任意類型的互斥鎖搭配使用(如:遞歸互斥鎖、定時(shí)互斥鎖等)
條件變量常用的成員函數(shù)
| wait() | 阻塞當(dāng)前線程,等待條件成立 |
| wait_for() | 阻塞當(dāng)前線程的過程中,該函數(shù)會(huì)自動(dòng)調(diào)用unlock()解鎖,令其他線程使用公共資源。當(dāng)條件成立或超過指定的等待時(shí)間,該函數(shù)自動(dòng)調(diào)用lock()加鎖,同時(shí)令線程繼續(xù)執(zhí)行 |
| wait_until() | 與wait_for() 類似,區(qū)別是其可以設(shè)定一個(gè)具體的時(shí)間點(diǎn),當(dāng)條件成立或等待時(shí)間超過了指定的時(shí)間點(diǎn),函數(shù)自動(dòng)加鎖,線程執(zhí)行 |
| notify_one() | 喚醒一個(gè)等待的線程 |
| notify_all() | 喚醒所有等待線程 |
關(guān)于wait() :
調(diào)用wait()1先獲得mutex,2線程被阻塞,當(dāng)wait陷入休眠是會(huì)自動(dòng)釋放mutex。直到另外某個(gè)線程調(diào)用 notify_one或notify_all喚醒了當(dāng)前線程。當(dāng)線程被喚醒時(shí),此時(shí)線程是已經(jīng)自動(dòng)占有了mutex。
3.例
1:兩線程交替打印奇偶數(shù)
#include<iostream> #include<thread> #include<mutex> using namespace std; std::mutex data_mutex; std::condition_variable data_var; bool tag = true; // odd : 1 // even: 2 // odd : 3 // even : 4void printodd() // 打印奇數(shù) {std::unique_lock<std::mutex> ulock(data_mutex);for (int odd = 1; odd <= 100; odd += 2){while (!tag){data_var.wait(ulock);}cout << "odd: " << odd << endl;tag = false;data_var.notify_all();} } void printeven() //打印偶數(shù) {std::unique_lock<std::mutex> ulock(data_mutex);for (int even = 2; even <= 100; even += 2){ while (tag){data_var.wait(ulock);// 1 2 }cout << "even: " << even << endl;tag = true;data_var.notify_all();} }int main() {thread thodd(printodd);thread theven(printeven);thodd.join();theven.join();return 0; }參考文獻(xiàn):
C++多線程unique_lock詳解
總結(jié)
以上是生活随笔為你收集整理的C11 多线程初学1的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: net core体系-web应用程序-4
- 下一篇: HDU 4383 To The Moon