創建線程的函數,頭文件thread。參數可以是函數名、仿函數、lambda表達式、類等等。
創新互聯是一家專業提供江漢企業網站建設,專注與做網站、網站設計、H5高端網站建設、小程序制作等業務。10年已為江漢眾多企業、政府機構等服務。創新互聯專業網站建設公司優惠進行中。join等待子線程執行完畢
子線程和子進程的死亡是有些區別的。主進程執行完成后,如果子進程沒有執行完會被系統init托管;主線程執行完后,如果子線程還沒有執行完,子線程會被強制結束。這就有了join函數,等待子線程執行完后在繼續執行。
detach守護線程,detach的作用是使主線程結束后,子線程不會強制結束
joinable判斷線程是否執行了join或者detach這兩個函數,沒有調用返回true
線程傳遞參數注意事項 線程中函數參數? 包含#include 頭文件
lock(),unlock()
步驟:1.lock(),2.操作共享數據,3.unlock()。
lock()和unlock()要成對使用
2.2 lock_guard類模板
lock_guard sbguard(myMutex);
取代lock()和unlock()
lock_guard構造函數執行了mutex::lock();在作用域結束時,調用析構函數,執行mutex::unlock()
? 兩個線程都已經鎖了部分資源,還在互相請求對方已經上鎖的資源,都不釋放資源,就會造成死鎖
解決死鎖std::lock()函數模板
std::lock_guard的std::adopt_lock參數
unique_lock比lock_guard靈活很多(多出來很多用法),效率差一點。
unique_lockmyUniLock(myMutex);
unique_lock的第二個參數std::condition_variable實際上是一個類,是一個和條件相關的類,說白了就是等待一個條件達成。
列舉一些他的成員函數
wait()線程等待,并且會放下鎖
wait(線程名,條件函數(可以省略默認true))
調用該方法后會進入堵塞狀態,需要等待比額的線程調用notify_one()或者notify_all()來喚醒,喚醒后會嘗試繼續拿起釋放掉的鎖
notify_one()喚醒一個執行過wait還在等待的線程,無法指定喚醒哪一個,是隨機喚醒1個
notify_all()喚醒所有執行了wait還在等待的線程
future、saync多線程如果函數有返回值,可以使用這兩個去接收返回值
std::future result1 = std::async(mythread);
執行futrue的get方法,就可以獲得mythread的返回值,如果函數還沒有運行完,那么會進入堵塞,一直到有返回值再繼續
futrue的wait就是等待返回值,是一個堵塞的方法。
saync的參數saync有兩個參數,第一個參數是如何創建線程,第二個參數是線程函數名字
如果不指定,就是兩個隨機
std::launch::deferred該參數線程不會直接創建線程,而且等待執行。
當用戶調用get方法的時候,才會執行線程。
注意:他不會創建線程,也是在主線程中執行的方法
std::launch::async該參數就是直接創建線程直接。是直接執行的
std::packaged_task類模板,它的模板參數是各種可調用對象,通過packaged_task把各種可調用對象包裝起來,方便將來作為線程入口函數來調用。
std::packaged_task
std::thread t1(std::ref(mypt), 1);
并不會直接調用線程,還是需要使用thread去創建顯示,他的作用只是打包
可以通過 get_future(); 獲取返回值
std::promise類模板我們能夠在某個線程中給它賦值,然后我們可以在其他線程中,把這個值取出來
std::promise myprom;
std::thread t1(mythread, std::ref(myprom), 180);
t1.join(); //在這里線程已經執行完了
std::future fu1 = myprom.get_future(); //promise和future綁定,用于獲取線程返回值
把他當成一個參數傳入,在線程中用setValue來改變他的值,在主線程獲取參數
std::async和std::thread()區別:std::thread()如果系統資源緊張可能出現創建線程失敗的情況,如果創建線程失敗那么程序就可能崩潰,而且不容易拿到函數返回值(不是拿不到)
std::async()創建異步任務。可能創建線程也可能不創建線程,并且容易拿到線程入口函數的返回值;
由于系統資源限制:
①如果用std::thread創建的線程太多,則可能創建失敗,系統報告異常,崩潰。
②如果用std::async,一般就不會報異常,因為如果系統資源緊張,無法創建新線程的時候,async不加額外參數的調用方式就不會創建新線程。而是在后續調用get()請求結果時執行在這個調用get()的線程上。
如果你強制async一定要創建新線程就要使用 std::launch::async 標記。承受的代價是,系統資源緊張時可能崩潰。
③根據經驗,一個程序中線程數量 不宜超過100~200 。
std::atomic原子類,執行不會被中斷
只能使用++ – 或者+=類似的運算符才可以保證原子性
Windows臨界區臨界區跟上鎖類似,有進入臨界區,離開臨界區,作用和和鎖是一樣的。
創建臨界區CRITICAL_SECTION my_winsec;
初始化臨界區InitializeCriticalSection(&my_winsec)
進入臨界區EnterCriticalSection(&my_winsec);
是可以重復進入的,mutex是無法重復lock的
離開臨界區LeaveCriticalSection(&my_winsec);
手寫自動自動離開的臨界區class CWinLock {public:
CWinLock(CRITICAL_SECTION *pCritmp)
{my_winsec =pCritmp;
EnterCriticalSection(my_winsec);
}
~CWinLock()
{LeaveCriticalSection(my_winsec)
};
private:
CRITICAL_SECTION *my_winsec;
};
遞歸鎖
獨占互斥量 std::recursive_mutexstd::mutex 獨占式互斥量
std::recursive_mutex:允許在同一個線程中同一個互斥量多次被 lock() ,(但是遞歸加鎖的次數是有限制的,太多可能會報異常),效率要比mutex低。
如果你真的用了 recursive_mutex 要考慮代碼是否有優化空間,如果能調用一次 lock()就不要調用多次。
帶超時的互斥量 std::timed_mutex 和 std::recursive_timed_mutexstd::timed_mutex:是待超時的獨占互斥量try_lock_for():
等待一段時間,如果拿到了鎖,或者超時了未拿到鎖,就繼續執行(有選擇執行)
try_lock_until():
兩者的區別就是一個參數是時間段,一個參數是時間點
自旋鎖(spinlock):是指當一個線程在獲取鎖的時候,如果鎖已經被其它線程獲取,那么該線程將循環等待,然后不斷的判斷鎖是否能夠被成功獲取,直到獲取到鎖才會退出循環。
獲取鎖的線程一直處于活躍狀態,但是并沒有執行任何有效的任務,使用這種鎖會造成busy-waiting。即不斷的消耗cpu
它是為實現保護共享資源而提出一種鎖機制。其實,自旋鎖與互斥鎖比較類似,它們都是為了解決對某項資源的互斥使用。無論是互斥鎖,還是自旋鎖,在任何時刻,最多只能有一個保持者,也就說,在任何時刻最多只能有一個執行單元獲得鎖。但是兩者在調度機制上略有不同。對于互斥鎖,如果資源已經被占用,資源申請者只能進入睡眠狀態。但是自旋鎖不會引起調用者睡眠,如果自旋鎖已經被別的執行單元保持,調用者就一直循環在那里看是否該自旋鎖的保持者已經釋放了鎖,”自旋”一詞就是因此而得名。
class CAS
{private:
std::atomicflag;
public:
CAS():flag(false) {}
~CAS() {}
CAS(const CAS& s) = delete;
CAS& operator=(const CAS&) = delete;
void lock()
{bool expect = false;
while (!flag.compare_exchange_strong(expect, true))
{ expect = false;
}
}
void unlock()
{flag.store(false);
}
};
compare_exchange_strong當前值與期望值(expect)相等時,修改當前值為設定值(desired,第二個參數),返回true
當前值與期望值(expect)不等時,將期望值(expect)修改為當前值,返回false
自旋鎖:線程獲取鎖的時候,如果鎖被其他線程持有,則當前線程將循環等待,直到獲取到鎖。
自旋鎖等待期間,線程的狀態不會改變,線程一直是用戶態并且是活動的(active)。
自旋鎖如果持有鎖的時間太長,則會導致其它等待獲取鎖的線程耗盡CPU。
自旋鎖本身無法保證公平性,同時也無法保證可重入性。
基于自旋鎖,可以實現具備公平性和可重入性質的鎖
讀寫鎖相比互斥鎖,讀寫鎖允許更高的并行性,互斥量要么鎖住狀態要么不加鎖,而且一次只有一個線程可以加鎖。
讀寫鎖可以有三種狀態:
鎖定互斥。若另一線程已鎖定互斥,則lock的調用線程將阻塞執行,直至獲得鎖。
若已以任何模式(共享或排他性)占有 mutex 的線程調用 lock ,則行為未定義。也就是說,已經獲得讀模式鎖或者寫模式鎖的線程再次調用lock的話,行為是未定義的。
注意:通常不直接使用std::shared_mutex::lock(),而是通過unique_lock或者lock_guard進行管理。
解鎖互斥。
互斥必須為當前執行線程所鎖定,否則行為未定義。如果當前線程不擁有該互斥還去調用unlock,那么就不知道去unlock誰,行為是未定義的。
注意:通常不直接調用 unlock() 而是用 std::unique_lock 與 std::lock_guard 管理排他性鎖定。
相比mutex,shared_mutex還擁有lock_shared函數。
該函數獲得互斥的共享所有權。若另一線程以排他性所有權保有互斥,則lock_shared的調用者將阻塞執行,直到能取得共享所有權。
若已以任何模式(排他性或共享)占有 mutex 的線程調用 lock_shared ,則行為未定義。即:當以讀模式或者寫模式擁有鎖的線程再次調用lock_shared時,行為是未定義的,可能產生死鎖。
若多于實現定義大數量的共享所有者已以共享模式鎖定互斥,則 lock_shared 阻塞執行,直至共享所有者的數量減少。所有者的大數量保證至少為 10000。
注意:通常不直接調用 lock_shared() 而是用 std::shared_lock 管理共享鎖定。
shared_lock與unique_lock的使用方法類似、
將互斥從調用方線程的共享所有權釋放。
當前執行線程必須以共享模式鎖定互斥,否則行為未定義。
通常不直接調用 unlock_shared() 而是用 std::shared_lock 管理共享鎖定。
你是否還在尋找穩定的海外服務器提供商?創新互聯www.cdcxhl.cn海外機房具備T級流量清洗系統配攻擊溯源,準確流量調度確保服務器高可用性,企業級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧
名稱欄目:C++多線程筆記-創新互聯
文章轉載:http://vcdvsql.cn/article22/cciecc.html
成都網站建設公司_創新互聯,為您提供App開發、自適應網站、動態網站、響應式網站、靜態網站、網站營銷
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯