簡介
併發能夠充分利用多核心處理器,但並行程式設計卻面臨著嚴峻的挑戰。
並行程式設計的乙個常見問題是資料同步,即多個語句同時訪問同一資源,當乙個執行緒在寫,而另乙個在讀時,就會造成不可預料的後果。
加鎖可以在避免上述問題,但使用鎖本身也帶來了一系列問題,如死鎖、效率低下等。不良的**也可能造成cpu空轉等待等資源浪費。
在c++11之前,語言或標準庫都沒有對併發進行任何的支援。但c++11提供了以下支援:
標準庫提供了高階介面,可以啟動執行緒,它是架構在低層介面上的。提供的低層介面包括mutex/atomic。
高階介面async()和future
它們的功能:
注意,async()是嘗試讓函式在後台執行,不提供強制性保證。具體地說:
比如要計算兩個資料的各,這兩個資料是兩個函式的返回值,通常的順序型程式設計為:func1() + func2()。
並行處理程式如下:
#include
#include
#include
#include
#include
#include
using
namespace std;
intdosomething
(char c)
return c;
}int
func1()
intfunc2()
intmain()
兩個函式會以視覺化的方式列印字元,並最終返回該字元的int值。注意以下幾點:
future的get()函式確保非同步函式最終被呼叫,具體地說,以下三種情況之一會發生:
這樣比通常的順序呼叫節省約func1的執行時間
為了取得最佳效果,通常程式應使呼叫async和get之間的間隔盡量大
可以使用引數強迫async不推遲目標函式的執行,如async(std::launch::async, func1)
,但這可能會丟擲異常
也可以強制延遲函式的執行,如async(std::launch::deferred, func1)
,只有在呼叫get時,函式都會被執行,適用於緩式求值的情況
以上程式未考慮資料同步和異常處理
低層介面:thread/promise
thread
可以直接使用thread物件啟動執行緒:
std::thread t(dosomething);
注意,要麼執行緒被join,要麼將它detach,否則會導致程式崩潰。
相對高階介面async,它的區別:
promise
future使用promise的get_future函式獲取關聯,然後,對於promise設定的值(set_value),future可以獲取(get)。
示例如下:
#include
#include
#include
#include
#include
#include
#include
using
namespace std;
void
dosomething
(std::promise
& p)
string s =
string
("char "
)+ c +
" processed"
; p.
set_value
(std::
move
(s));}
catch(.
..)}
intmain()
catch(.
..)}
資料同步
資料競險及資料不同步的問題不再重複,c++標準庫提供了多種方法使程式在併發資料訪問方面獲得額外的保證:
這些方式從上到下,從高階到低階,根據使用場景的不同選擇使用。
關於各類的用法就不展開敘述了,可以參考相關示例。
最後c++11對併發程式設計提供的支援遠不止這些,可以在實踐中不斷深入學習。
C 11併發程式設計 多執行緒std thread
c 11引入了thread類,大大降低了多執行緒使用的複雜度,原先使用多執行緒只能用系統的api,無法解決跨平台問題,一套 平台移植,對應多執行緒 也必須要修改。現在在c 11中只需使用語言層面的thread可以解決這個問題。所需標頭檔案 thread noexcept 乙個空的std thread...
C 11 多執行緒 併發程式設計總結
建立std thread,一般會繫結乙個底層的執行緒。若該thread還繫結好函式物件,則即刻將該函式執行於thread的底層執行緒。執行緒相關的很多預設是move語義,因為在常識中線程複製是很奇怪的行為。joinable 是否可以阻塞至該thread繫結的底層執行緒執行完畢 倘若該thread沒有...
C 11併發程式設計 多執行緒std thread
一 概述 c 11引入了thread類,大大降低了多執行緒使用的複雜度,原jtpbyn先使用多執行緒只能用系統的api,無法解決跨平台問題,一套 平台移植,對應多執行緒 也必須要修改。現在在c 11中只需使用語言層面的thread可以解決這個問題。所需標頭檔案 二 建構函式 1.預設建構函式 2.初...