国产激情自拍_国产9色视频_丁香花在线电影小说观看 _久久久久国产精品嫩草影院

首頁 > 編程 > C++ > 正文

探究在C++程序并發(fā)時(shí)保護(hù)共享數(shù)據(jù)的問題

2020-05-23 14:18:16
字體:
供稿:網(wǎng)友

這篇文章主要介紹了探究在C++程序并發(fā)時(shí)保護(hù)共享數(shù)據(jù)的問題,也有利于大家更好地理解C++多線程的一些機(jī)制,需要的朋友可以參考下

我們先通過一個(gè)簡單的代碼來了解該問題。

同步問題

我們使用一個(gè)簡單的結(jié)構(gòu)體 Counter,該結(jié)構(gòu)體包含一個(gè)值以及一個(gè)方法用來改變這個(gè)值:

 

 
  1. struct Counter { 
  2. int value; 
  3.  
  4. void increment(){ 
  5. ++value; 
  6. }; 

然后啟動(dòng)多個(gè)線程來修改結(jié)構(gòu)體的值:

 

 
  1. int main(){ 
  2. Counter counter; 
  3.  
  4. std::vector<std::thread> threads; 
  5. for(int i = 0; i < 5; ++i){ 
  6. threads.push_back(std::thread([&counter](){ 
  7. for(int i = 0; i < 100; ++i){ 
  8. counter.increment(); 
  9. })); 
  10.  
  11. for(auto& thread : threads){ 
  12. thread.join(); 
  13.  
  14. std::cout << counter.value << std::endl; 
  15.  
  16. return 0; 

我們啟動(dòng)了5個(gè)線程來增加計(jì)數(shù)器的值,每個(gè)線程增加了100次,然后在線程結(jié)束時(shí)打印計(jì)數(shù)器的值。

但我們運(yùn)行這個(gè)程序的時(shí)候,我們是希望它會(huì)答應(yīng)500,但事實(shí)不是如此,沒人能確切知道程序?qū)⒋蛴∈裁唇Y(jié)果,下面是在我機(jī)器上運(yùn)行后打印的數(shù)據(jù),而且每次都不同:

 

 
  1. 442 
  2. 500 
  3. 477 
  4. 400 
  5. 422 
  6. 487 

問題的原因在于改變計(jì)數(shù)器值并不是一個(gè)原子操作,需要經(jīng)過下面三個(gè)操作才能完成一次計(jì)數(shù)器的增加:

首先讀取 value 的值

然后將 value 值加1

將新的值賦值給 value

但你使用單線程來運(yùn)行這個(gè)程序的時(shí)候當(dāng)然沒有任何問題,因此程序是順序執(zhí)行的,但在多線程環(huán)境中就有麻煩了,想象下下面這個(gè)執(zhí)行順序:

Thread 1 : 讀取 value, 得到 0, 加 1, 因此 value = 1

Thread 2 : 讀取 value, 得到 0, 加 1, 因此 value = 1

Thread 1 : 將 1 賦值給 value,然后返回 1

Thread 2 : 將 1 賦值給 value,然后返回 1

這種情況我們稱之為多線程的交錯(cuò)執(zhí)行,也就是說多線程可能在同一個(gè)時(shí)間點(diǎn)執(zhí)行相同的語句,盡管只有兩個(gè)線程,交錯(cuò)的現(xiàn)象也很明顯。如果你有更多的線程、更多的操作需要執(zhí)行,那么這個(gè)交錯(cuò)是必然發(fā)生的。

有很多方法來解決線程交錯(cuò)的問題:

信號量 Semaphores

原子引用 Atomic references

Monitors

Condition codes

Compare and swap

在這篇文章中我們將學(xué)習(xí)如何使用信號量來解決這個(gè)問題。信號量也有很多人稱之為互斥量(Mutex),同一個(gè)時(shí)間只允許一個(gè)線程獲取一個(gè)互斥對象的鎖,通過 Mutex 的簡單屬性就可以用來解決交錯(cuò)的問題。

使用 Mutex 讓計(jì)數(shù)器程序是線程安全的

在 C++11 線程庫中,互斥量包含在 mutex 頭文件中,對應(yīng)的類是 std::mutex,有兩個(gè)重要的方法 mutex:lock() 和 unlock() ,從名字上可得知是用來鎖對象以及釋放鎖對象。一旦某個(gè)互斥量被鎖,那么再次調(diào)用 lock() 返回堵塞值得該對象被釋放。

為了讓我們剛才的計(jì)數(shù)器結(jié)構(gòu)體是線程安全的,我們添加一個(gè) set:mutext 成員,并在每個(gè)方法中通過 lock()/unlock() 方法來進(jìn)行保護(hù):

 

 
  1. struct Counter { 
  2. std::mutex mutex; 
  3. int value; 
  4.  
  5. Counter() : value(0) {} 
  6.  
  7. void increment(){ 
  8. mutex.lock(); 
  9. ++value; 
  10. mutex.unlock(); 
  11. }; 

然后我們再次測試這個(gè)程序,打印的結(jié)果就是 500 了,而且每次都一樣。

異常和鎖

現(xiàn)在讓我們來看另外一種情況,想象我們的的計(jì)數(shù)器有一個(gè)減操作,并在值為0的時(shí)候拋出異常:

 

 
  1. struct Counter { 
  2. int value; 
  3.  
  4. Counter() : value(0) {} 
  5.  
  6. void increment(){ 
  7. ++value; 
  8.  
  9. void decrement(){ 
  10. if(value == 0){ 
  11. throw "Value cannot be less than 0"
  12.  
  13. --value; 
  14. }; 

然后我們不需要修改類來訪問這個(gè)結(jié)構(gòu)體,我們創(chuàng)建一個(gè)封裝器:

 

 
  1. struct ConcurrentCounter { 
  2. std::mutex mutex; 
  3. Counter counter; 
  4.  
  5. void increment(){ 
  6. mutex.lock(); 
  7. counter.increment(); 
  8. mutex.unlock(); 
  9.  
  10. void decrement(){ 
  11. mutex.lock(); 
  12. counter.decrement();  
  13. mutex.unlock(); 
  14. }; 

大部分時(shí)候該封裝器運(yùn)行挺好,但是使用 decrement 方法的時(shí)候就會(huì)有異常發(fā)生。這是一個(gè)大問題,一旦異常發(fā)生后,unlock 方法就沒被調(diào)用,導(dǎo)致互斥量一直被占用,然后整個(gè)程序就一直處于堵塞狀態(tài)(死鎖),為了解決這個(gè)問題我們需要用 try/catch 結(jié)構(gòu)來處理異常情況:

 

 
  1. void decrement(){ 
  2. mutex.lock(); 
  3. try { 
  4. counter.decrement(); 
  5. catch (std::string e){ 
  6. mutex.unlock(); 
  7. throw e; 
  8. mutex.unlock(); 

這個(gè)代碼并不難,但看起來很丑,如果你一個(gè)函數(shù)有 10 個(gè)退出點(diǎn),你就必須為每個(gè)退出點(diǎn)調(diào)用一次 unlock 方法,或許你可能在某個(gè)地方忘掉了 unlock ,那么各種悲劇即將發(fā)生,悲劇發(fā)生將直接導(dǎo)致程序死鎖。

接下來我們看如何解決這個(gè)問題。

自動(dòng)鎖管理

當(dāng)你需要包含整段的代碼(在我們這里是一個(gè)方法,也可能是一個(gè)循環(huán)體或者其他的控制結(jié)構(gòu)),有這么一種好的解決方法可以避免忘記釋放鎖,那就是 std::lock_guard.

這個(gè)類是一個(gè)簡單的智能鎖管理器,但創(chuàng)建 std::lock_guard 時(shí),會(huì)自動(dòng)調(diào)用互斥量對象的 lock() 方法,當(dāng) lock_guard 析構(gòu)時(shí)會(huì)自動(dòng)釋放鎖,請看下面代碼:

 

 
  1. struct ConcurrentSafeCounter { 
  2. std::mutex mutex; 
  3. Counter counter; 
  4.  
  5. void increment(){ 
  6. std::lock_guard<std::mutex> guard(mutex); 
  7. counter.increment(); 
  8.  
  9. void decrement(){ 
  10. std::lock_guard<std::mutex> guar(mutex); 
  11. mutex.unlock(); 
  12. }; 

是不是看起來爽多了?

使用 lock_guard ,你不再需要考慮什么時(shí)候要釋放鎖,這個(gè)工作已經(jīng)由 std::lock_guard 實(shí)例幫你完成。

結(jié)論

在這篇文章中我們學(xué)習(xí)了如何通過信號量/互斥量來保護(hù)共享數(shù)據(jù)。需要記住的是,使用鎖會(huì)降低程序性能。在一些高并發(fā)的應(yīng)用環(huán)境中有其他更好的解決辦法,不過這不在本文的討論范疇之內(nèi)。

你可以在 Github 上獲取本文的源碼.

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
国产激情自拍_国产9色视频_丁香花在线电影小说观看 _久久久久国产精品嫩草影院
国产精品久久在线| 伊人网在线免费观看| 亚洲欧美综合乱码精品成人网| 午夜av电影| 国产porn在线| 亚洲成人福利| 激情综合丁香| 国产激情视频在线| 91美女主播在线视频| 亚洲视频手机在线观看| 久热中文字幕| 精品视频在线一区二区| 亚洲国产日韩成人综合天堂| 亚洲wwwwww| 国产卡二和卡三的视频| 国产色在线播放| 在线观看国产福利视频| 在线看黄网站| 国产一级在线| 天天操夜夜做| 91精品专区| 99视频免费在线观看| 99久热re在线精彩视频| 日本高清中文字幕在线| 国产私人影院| 美女被人操视频在线观看| 国产视频青青| 国产原创精品视频| 免费99热在线观看| 国产www网站| 中文字幕在线视频免费观看| 在线中文字幕资源| 九九热视频免费观看| av免费在线观看网站| 国产欧美日韩专区| 成人超碰在线| 免费看av大片| 青草在线视频在线观看| 尤物在线精品视频| 国产黄色片大全| 中文字幕专区| 国产秀色在线www免费观看| 黄色在线视频观看网站| www.狠狠操| 欧美性猛交xxxxbbbb| 亚洲激情丁香| 亚洲尤物在线视频| 精品国产免费第一区二区| 国产精品入口免费麻豆| 国产剧情av在线| 中文字幕国产欧美| 国产激情自拍视频| 亚洲电影先锋| 欧美精品一区二区三区免费| 免费日本黄色| 国产美女性感在线观看懂色av| 麻豆网站在线免费观看| 国产在线观看av| 国产一二三区在线观看| 国产福利视频在线观看| 亚洲综合在线不卡| 九九热免费视频| 久久精品最新免费国产成人| 91xxx在线观看| 777电影在线观看| 性网站在线播放| 国产伦精品一区二区三区高清版禁| 国产乱子伦三级在线播放| 国产网站免费观看| 亚洲一道本在线| 国产网站免费看| 免费一区二区三区视频狠狠| 国产小视频免费在线网址| 97视频在线观看网站| 欧美性猛交p30| 国产成人亚洲综合小说区| 四虎久久影院| 国产午夜视频在线观看| eeuss影影院www在线播放| 午夜免费福利在线观看| 日本成人免费网站| 精品一区二区三区免费站| 国产字幕在线看| 99久热re在线精彩视频| 懂色av一区| 女子免费在线观看视频www| 国产精品186在线观看在线播放| 免费国产视频| av文字幕在线观看| 国产黄色av免费看| 中文字幕不卡免费视频| 免费电影网站在线视频观看福利| 国产偷倩在线播放| 国产免费av高清在线| av在线你懂的| av三级在线观看| 国产va在线观看| 国产精品久久久高清免费| 国产中文字幕在线看| 欧美精品另类| а√最新版在线天堂| 亚洲国产aⅴ精品| 亚洲一区二区三区在线观看网站| 国产精品你懂的在线观看| 中文字幕一区免费| 中文字幕人成高视频| 最近中文字幕av免费高清| 热99re久久精品这里都是免费| 99在线视频影院| 日本视频一二三区中文字幕| av在线1区2区| 一本免费视频| 日本韩国精品一区二区| 开心丁香婷婷深爱五月| 久久精品视频免费看| 国产原创在线播放| 中文字幕在线影院| 91这里只有精品| 欧美高清xxxx性| 狠狠操视频网| 国产福利在线播放麻豆| 中文av资源在线| 在线看黄网站| 国内自拍视频在线观看| 国产性网软件大全| 在线成人一区| 91超碰在线免费| 91www在线观看| 人成在线免费视频| 国产福利一区二区在线精品| jizz一区二区三区| 国产美女免费观看| 2018狠狠干| 欧美艹逼视频| 精品国内一区二区三区免费视频 | 天天爱天天做色综合| 国产精品视频h| 阿v免费在线观看| 国产高清在线观看| 超碰免费在线观看| 精品国产高清自在线一区二区三区| 狠狠干在线视频| av在线free| 国产视频一二三区| 国产麻豆精品一区二区三区v视界| 在线午夜视频| 91精品国产高久久久久久五月天| 狠狠狠综合7777久夜色撩人| 国产传媒在线播放| 中文字幕在线免费| 福利视频网址导航| 免费一区二区在线观看| 精品国产99久久久久久| 国产网站av| 午夜视频免费在线观看| 国产在线观看网站| 四虎www视频| 四虎成人精品在永久免费| 一区二区三区四区在线免费视频| av在线免费播放| 狠狠操狠狠色| av文字幕在线观看| 国产黄色小视频| 免费中文字幕| 天天艹天天操| 日本成人免费网站| www.三级.com| а√最新版在线天堂| 日本三级视频网站| 免费国产在线视频| 懂色一区二区三区| 国产免费av网站| 国产麻豆精品视频一区二区 | 国产二区三区四区| 91精品国产91久久久久久青草| 国产高清在线视频| 在线国产一级| 天天草天天草| 成年黄网站在线观看免费| 国产精品自拍在线观看| 国产精品入口麻豆电影| 国产成人福利| 四虎www视频| 中文字幕国产欧美| 影音先锋在线中文字幕| 欧美日韩在线精品成人综合网| 激情丁香婷婷| 国产激情视频在线| 亚洲国产成人综合| 国产蜜臀在线| 在线观看免费观看在线91| 久久国产精品黑丝| 91xxx在线观看| 中文产幕区在线观看| 黄色av电影在线播放| 在线视频色在线| 成视频年人免费看黄网站| 18av在线视频| 天堂在线中文资源| 青青在线视频|