C++11 多執行緒同步
多執行緒能提高程式的效率,但同時也帶來了相應的問題----資料競爭。當多個執行緒同時操作同一個變數時,就會出現資料競爭。出現數據競爭,一般會用臨界區(Critical Section)、互斥量(Mutex)、訊號量(Semaphore)、事件(Event)這四種方法來完成執行緒同步。
1、臨界區
對於臨界資源,多執行緒必須互斥地對它進行訪問。每個執行緒訪問臨界資源的那段程式碼就稱為臨界區。它保證每次只能有一個執行緒進入臨界區。有一個執行緒進入臨界區後其他試圖訪問臨界區的執行緒會被掛起。臨界區被釋放後,其他執行緒才可以繼續搶佔。幾種同步處理中,臨界區速度最快,但它只能實現同進程中的多個執行緒同步,無法實現多程序同步。c++11並沒有為我們提供臨界區類。
2、互斥量
互斥量與臨界區相似,但臨界區不支援多程序,而mutex支援多程序。c++11標準庫中提供了mutex類。
- #include "stdafx.h"
- #include <vector>
- #include <thread>
- #include <iostream>
- #include <mutex>
- usingnamespace std;
- mutex sLock;
- int i = 0;
- void test()
- {
- for (int j = 0; j < 1000; j++)
- {
-
sLock.lock();
- i++;
- sLock.unlock();
- }
- }
- int main(int argc, _TCHAR* argv[])
- {
- vector<thread> v;
- for (int j = 0; j < 100; j++)
- {
- v.emplace_back(test);
- }
- for(auto& t : v)
- {
- t.join();
- }
-
cout << i << endl;
- }
曾有人對c++11中的thread和mutex效能進行了測試。點選開啟連結根據他的測試結果,std::thread的效能損耗不大,但std::mutex的效能損耗非常大。所以如果設計中要考慮效能的話,應該避免使用c++11標準庫中的mutex
3、訊號量
訊號量物件對執行緒的同步方式與前面幾種方法不同,訊號量允許多個執行緒同時使用共享資源。它的原理是:
P操作 申請資源:
(1)S減1;
(2)若S減1後仍大於等於零,則程序繼續執行;
(3)若S減1後小於零,則該程序被阻塞後進入與該訊號相對應的佇列中,然後轉入程序排程。
V操作 釋放資源:
(1)S加1;
(2)若相加結果大於零,則程序繼續執行;
(3)若相加結果小於等於零,則從該訊號的等待佇列中喚醒一個等待程序,然後再返回原程序繼續執行或轉入程序排程。
4、事件
事件物件可以通過通知操作的方式來保持執行緒同步。
******************************************************************************************************************************************什麼是條件變數?
條件變數是一種同步機制,允許執行緒掛起,直到共享資料上的某些條件得到滿足。條件變數上的基本操作有:觸發條件(當條件變為 true 時);等待條件,掛起執行緒直到其他執行緒觸發條件。條件變數要和互斥量相聯結,以避免出現條件競爭--一個執行緒預備等待一個條件變數,當它在真正進入等待之前,另一個執行緒恰好觸發了該條件。
什麼意思呢?不清楚沒關係。看了例子就知道了:問題描述:假設有一個bool型全域性變數 isTrue ,現有10個執行緒,執行緒流程如下:當isTrue為真時,doSomething;否則掛起執行緒,直到條件滿足。那麼,用thread和mutex如何實現這個功能呢?
- #include <vector>
- #include <iostream>
- #include <thread>
- #include <mutex>
- #include <chrono>
- usingnamespace std;
- bool isTrue = false;
- void doSomething()
- {
- cout << "this is : " << this_thread::get_id() << endl;
- }
- void thread_Func()
- {
- while (!isTrue)
- this_thread::yield();
- doSomething();
- }
- int main()
- {
- vector<thread> v;
- v.reserve(10);
- for (int i = 0; i < 10; i++)
- {
- v.emplace_back(thread_Func);
- }
- this_thread::sleep_for(chrono::seconds(2));
- isTrue = true;
- for (auto& t : v)
- {
- t.join();
- }
- return 1;
- }
nice,條件變數就是幹這事的!
先來看看條件變數的介紹:
條件變數能夠掛起呼叫執行緒,直到接到通知才會喚醒執行緒。它使用unique_lock<Mutex>來配合完成。下面是用條件變數實現需求:
- #include <iostream>
- #include <vector>
- #include <thread>
- #include <mutex>
- #include <chrono>
- #include <condition_variable>
- usingnamespace std;
- bool isTrue = false;
- std::mutex mtx;
- std::condition_variable cv;
- void doSomething()
- {
- cout << "this is : " << this_thread::get_id() << endl;
- }
- void thread_Func()
- {
- unique_lock<mutex> loc(mtx);
- while (!isTrue)
- cv.wait(loc);
- doSomething();
- }
- int main()
- {
- vector<thread> v;
- v.reserve(10);
- for (int i = 0; i < 10; i++)
- {
- v.emplace_back(thread_Func);
- }
- this_thread::sleep_for(chrono::seconds(2));
- {
- unique_lock<mutex> loc(mtx);
- isTrue = true;
- cv.notify_all();
- }
- for (auto& t : v)
- {
- t.join();
- }
- return 1;
- }
我們把while (!isTrue) cv.wait(loc)拆開:
1、條件判斷2、掛起執行緒
假如現在1執行完後,時間片輪轉,該子執行緒暫停執行。而恰好在這時,主執行緒修改了條件,並呼叫了cv.notify_all()函式。這種情況下,該子執行緒是收不到通知的,因為它還沒掛起。等下一次排程子執行緒時,子執行緒接著執行2將自己掛起。但現在主執行緒中的notify早已經呼叫過了,不會再調第二次了,所以該子執行緒永遠也無法喚醒了。
為了解決上面的情況,就要使用某種同步手段來給執行緒加鎖。而c++11的condition_variable選擇了用unique_lock<Mutex>來配合完成這個功能。並且我們只需要加鎖,條件變數在掛起執行緒時,會呼叫原子操作來解鎖。c++11還為我們提供了一個更方便的介面,連同條件判斷,一起放在條件變數裡。上面的執行緒函式可做如下修改:
- void thread_Func()
- {
- unique_lock<mutex> loc(mtx);
- cv.wait(loc, []() -> bool { return isTrue;} );
- doSomething();
- }
相關推薦
C++11 多執行緒同步
多執行緒能提高程式的效率,但同時也帶來了相應的問題----資料競爭。當多個執行緒同時操作同一個變數時,就會出現資料競爭。出現數據競爭,一般會用臨界區(Critical Section)、互斥量(Mutex)、訊號量(Semaphore)、事件(Event)這四種方法來完
C++11多執行緒程式設計 第十章: 使用packaged_task優雅的讓同步函式非同步執行
C++11 Multithreading – Part 10: packaged_task<> Example and Tutorial Varun July 2, 2017 C++11 Multithreading – Part 10: packaged_tas
[轉]c++11 多執行緒 future/promise
[轉自 https://blog.csdn.net/jiange_zh/article/details/51602938] 1. < future >標頭檔案簡介 Classes std::future std::future_error std::packaged_task std::pro
c++11多執行緒 thread
1.thread建構函式 default (1) thread() noexcept; initialization (2) template <class Fn, class... Args> explicit
C++11 多執行緒執行緒共享資料
共享資料的問題 這些在作業系統中都有詳細的介紹,可以回顧作業系統課程。。很典型的就是資料競爭問題。 互斥量保護資料 最原始的方式:使用std::mutex建立互斥量,使用成員lock()加鎖,使用成員unlock()解鎖。但是這種方式需要我們在每個函數出口都呼叫一次unloc
c++11多執行緒與執行緒池
最近需要開發一個高效能運算庫,涉及到c++多執行緒的應用,上次做類似的事情已經是4年多以前了,印象中還頗有些麻煩。悔當初做了就算了,也沒想著留點記錄什麼的。這次又研究了一番,發現用上c++11特性之後,現在已經比較簡單了,在此記錄一下。 最簡單的多執行緒情況,不涉及公共變數,各個執行緒之間獨
C++11多執行緒(1)
C++11中添加了duox多執行緒類,編寫C++程式可以直接使用C++11中的多執行緒庫,不必依賴於平臺多執行緒,這樣可以方便寫出誇平臺的多執行緒程式。多執行緒可以最大化利用計算機資源,提高程式碼的執行效率。 C++11中thread類提供兩
C++ 11 多執行緒下std::unique_lock與std::lock_guard的區別和用法
這裡主要介紹std::unique_lock與std::lock_guard的區別用法 先說簡單的 一、std::lock_guard的用法 std::lock_guard其實就是簡單的RAII封裝,在建構函式中進行加鎖,解構函式中進行解鎖,這樣可以保證函式退出時,鎖一定被釋放。 簡單來說,就是防止開
C++11多執行緒------std::async
std::async可以認為是封裝了一個std::promise,該函式返回一個std::future,用於獲取其他執行緒的資料。 一般有兩種模式: std::lanch::async:最常用的非同步模式,每次都要執行一遍 std::lanch::defer:只在第
C++11多執行緒---互斥量、鎖、條件變數的總結
關於互斥量std::mutex的總結 互斥量用於組成程式碼的臨界區。C++的多執行緒模型是基於記憶體的,或者說是基於程式碼片段的,這和我們作業系統學習的臨界區概念基本一致,但是與Golang不同,Golang是基於訊息模型的。 一個std::mutex的lock()和unlock
C++11多執行緒的原子操作
原子操作是同時只能有一個執行緒執行一個操作,不用使用互斥量即可實現,但是速度慢,而且一般只支援原生的型別,不夠靈活。更多的用處是作為訊號量進行使用。 示例程式碼,以int為例子: #include <atomic> #include <thread> #i
C++ 11 多執行緒--執行緒管理
說到多執行緒程式設計,那麼就不得不提並行和併發,多執行緒是實現併發(並行)的一種手段。並行是指兩個或多個獨立的操作同時進行。注意這裡是同時進行,區別於併發,在一個時間段內執行多個操作。在單核時代,多個執行緒是併發的,在一個時間段內輪流執行;在多核時代,多個執行緒可以實現真正的並行,在多核上真正獨立的並行執行。
C++11多執行緒程式設計 緒論及總結
C++11多執行緒程式設計 這一系列文章是從 https://thispointer.com/c11-multithreading-tutorial-series/ 轉過來的, 本來想翻譯一下, 但看了些內容, 用詞都不難, 讀英文沒有太大難度, 翻譯過來反而怕用詞不準畫蛇添
C++11多執行緒程式設計 第九章: std::async 更更優雅的寫多執行緒
C++11 Multithreading – Part 9: std::async Tutorial & Example Varun May 5, 2017 C++11 Multithreading – Part 9: std::async Tutorial &
C++11多執行緒程式設計 第八章: 使用 std::future std::promise 更優雅的獲取執行緒返回值
C++11 Multithreading – Part 8: std::future , std::promise and Returning values from Thread Varun June 20, 2015 C++11 Multithreading – Part
C++11多執行緒程式設計 第七章: 條件變數及其使用方法
C++11 Multithreading – Part 7: Condition Variables Explained Varun June 2, 2015 C++11 Multithreading – Part 7: Condition Variables Explain
C++11多執行緒程式設計 第五章: 使用鎖來解決竟態條件
C++11 Multithreading – Part 5: Using mutex to fix Race Conditions Varun February 22, 2015 C++11 Multithreading – Part 5: Using mutex to fi
C++11多執行緒程式設計 第四章: 共享資料和競態條件
C++11 Multithreading – Part 4: Data Sharing and Race Conditions Varun February 21, 2015C++11 Multithreading – Part 4: Data Sharing and Race Con
C++11多執行緒程式設計 第三章: 如何向執行緒傳參
C++11 Multithreading – Part 3: Carefully Pass Arguments to Threads Varun January 22, 2015 C++11 Multithreading – Part 3: Carefully Pass Ar
C++11多執行緒程式設計 第二章: join 和 detach 執行緒
C++11 Multithreading – Part 2: Joining and Detaching Threads Varun January 21, 2015 C++11 Multithreading – Part 2: Joining and De