亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁(yè) > 編程 > C++ > 正文

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

2020-05-23 14:18:16
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

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

我們先通過(guò)一個(gè)簡(jiǎn)單的代碼來(lái)了解該問(wèn)題。

同步問(wèn)題

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

 

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

然后啟動(dòng)多個(gè)線程來(lái)修改結(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è)線程來(lái)增加計(jì)數(shù)器的值,每個(gè)線程增加了100次,然后在線程結(jié)束時(shí)打印計(jì)數(shù)器的值。

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

 

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

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

首先讀取 value 的值

然后將 value 值加1

將新的值賦值給 value

但你使用單線程來(lái)運(yùn)行這個(gè)程序的時(shí)候當(dāng)然沒(méi)有任何問(wèn)題,因此程序是順序執(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í)行,也就是說(shuō)多線程可能在同一個(gè)時(shí)間點(diǎn)執(zhí)行相同的語(yǔ)句,盡管只有兩個(gè)線程,交錯(cuò)的現(xiàn)象也很明顯。如果你有更多的線程、更多的操作需要執(zhí)行,那么這個(gè)交錯(cuò)是必然發(fā)生的。

有很多方法來(lái)解決線程交錯(cuò)的問(wèn)題:

信號(hào)量 Semaphores

原子引用 Atomic references

Monitors

Condition codes

Compare and swap

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

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

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

為了讓我們剛才的計(jì)數(shù)器結(jié)構(gòu)體是線程安全的,我們添加一個(gè) set:mutext 成員,并在每個(gè)方法中通過(guò) lock()/unlock() 方法來(lái)進(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. }; 

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

異常和鎖

現(xiàn)在讓我們來(lái)看另外一種情況,想象我們的的計(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. }; 

然后我們不需要修改類來(lái)訪問(wèn)這個(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è)大問(wèn)題,一旦異常發(fā)生后,unlock 方法就沒(méi)被調(diào)用,導(dǎo)致互斥量一直被占用,然后整個(gè)程序就一直處于堵塞狀態(tài)(死鎖),為了解決這個(gè)問(wèn)題我們需要用 try/catch 結(jié)構(gòu)來(lái)處理異常情況:

 

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

接下來(lái)我們看如何解決這個(gè)問(wèn)題。

自動(dòng)鎖管理

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

這個(gè)類是一個(gè)簡(jiǎn)單的智能鎖管理器,但創(chuàng)建 std::lock_guard 時(shí),會(huì)自動(dòng)調(diào)用互斥量對(duì)象的 lock() 方法,當(dāng) lock_guard 析構(gòu)時(shí)會(huì)自動(dòng)釋放鎖,請(qǐ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. }; 

是不是看起來(lái)爽多了?

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

結(jié)論

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

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

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
国产免费不卡| 亚洲高清视频的网址| 人妻偷人精品一区二区三区| 青青草观看免费视频在线| 麻豆亚洲av成人无码久久精品| 国产一区二区在线观看免费播放| 蜜桃av噜噜一区二区三区小说| 欧美激情精品久久久久| 人妻精品一区一区三区蜜桃91| 国产又爽又黄的视频| 一本久道久久综合无码中文| 538精品在线观看| 99久久免费国产精品| 一区二区三区中文字幕精品精品| 特黄一区二区三区| 99精品视频99| 日韩av大片在线观看| 懂色av中文字幕一区二区三区| japanese在线| 韩国美女久久| 国产aⅴ夜夜欢一区二区三区| av中文字幕免费在线观看| 国产精品一区在线观看乱码| 国产xxxx视频| 欧美一级播放| 六月婷婷色综合| 日本成址在线观看| 欧美a级一区| 日韩av一二三区| 国产网友自拍视频| 久久久久久久伊人| 91欧美激情一区二区三区成人| 亚洲精品一区二三区| 激情综合亚洲| 日韩三级视频在线| 成人激情黄色小说| 成人美女av在线直播| 欧美三级视频在线| 成人黄色av电影| 中文有码一区| 永久免费无码av网站在线观看| 日本视频一区在线观看| 欧美特黄a级高清免费大片a级| 日本中文字幕免费观看| 国产亚洲精久久久久久| 性欧美高清come| 国产美女视频黄a视频免费| 日韩欧美中文字幕精品| 青青视频在线播放| 欧美mv日韩mv| www在线观看免费视频| 高清免费成人av| 特大黑人巨人吊xxxx| 国产精品美女在线播放| 成人污视频在线观看| bdsm在线观看播放视频| 91免费视频网站在线观看| 亚洲女人的天堂| 伊人久久亚洲综合| 欧美oldwomenvideos| **欧美大码日韩| 亚洲成人天堂网| 久久婷婷五月综合色丁香| 91久久久久| 懂色av一区二区三区| 国产精品福利无圣光在线一区| 久久久久久久伊人| 亚洲欧美激情另类| 国产日韩亚洲欧美| 69精品小视频| 五月天婷婷综合网| 国产精品无码免费播放| 91亚洲国产高清| 草草地址线路①屁屁影院成人| 中文有码在线| 一区二区三区四区不卡| 中国黄色一级视频| 成人福利视频| 正在播放精油久久| 日本黄色不卡视频| 91麻豆产精品久久久久久夏晴子| 国产精品综合网站| 亚洲一区在线观看视频| 538在线一区二区精品国产| 岛国毛片在线播放| 亚洲欧洲精品一区二区三区波多野1战4| 国产偷久久久精品专区| 日韩精品在线一区| 麻豆视频网站在线观看| 三上亚洲一区二区| 欧美风狂大伦交xxxx| 中日韩美女免费视频网站在线观看| 久久99久久99精品中文字幕| 在线观看毛片视频| 亚洲国产精品久久91精品| 在线看国产视频| 韩国三级电影久久久久久| 伊人久久久久久久久久久久久| 91超碰在线观看| 日本亚洲天堂| 中文字幕 视频一区| 精品国产一区二区三区四区阿崩| 亚洲欧美日韩一区二区三区在线| 国产成人aa精品一区在线播放| 国产盗摄——sm在线视频| 一区中文字幕在线观看| 亚洲欧美一区二区精品久久久| 99视频网站| 欧美成人手机在线视频| 99热这里只有精品首页| 国产精品国产一区二区三区四区| 欧美美女操人视频| 欧美亚洲国产另类| 欧美丰满少妇人妻精品| 一区二区三区视频免费在线观看| 久久超碰99| 欧美唯美清纯偷拍| 蜜臀99久久精品久久久久久软件| 最新四虎影在线在永久观看www| 精品视频在线一区二区在线| 中文字幕毛片| 97久久国产亚洲精品超碰热| 久久国产影院| 亚洲综合一区二区三区| 日韩少妇内射免费播放| 国产在线高清精品| 国产精品永久免费| 婷婷开心激情综合| 男女一区二区三区免费| 亚洲国产精品一区二区久久hs| 国产精品免费小视频| 欧美亚洲国产一区在线观看网站| 国产91精品看黄网站在线观看| 国产精品yjizz视频网一二区| 92精品国产成人观看免费| 久久精品夜色噜噜亚洲aⅴ| 91精品久久久久久久久青青| 成人黄色在线观看视频| av在线不卡网| 国产精品 欧美 日韩| 激情六月丁香| 日本三级中文字幕| 国产精品hd| 成人免费在线电影网| 亚洲男人第一天堂| 成人av一级片| 99精品国产一区二区三区2021| 无码人妻aⅴ一区二区三区69岛| 大片网站久久| 一区二区三区麻豆| 99精品国自产在线| 亚洲午夜久久久久久久| 先锋影音在线资源站91| 日韩欧美亚洲一区| 无套内谢丰满少妇中文字幕| 中文av一区二区三区| 日韩免费av片在线观看| a级在线观看视频| 国产精品三级视频| 欧美女激情福利| 伊人伊人伊人久久| 日韩三级在线观看| 日韩中文字幕视频网| 欧美写真视频一区| 九九热精品在线视频| 久久久影院一区二区三区| 国产综合精品一区二区三区| 精品资源在线| 视频一区二区三区不卡| 亚洲欧美成人一区二区三区| 97久久视频| 亚洲一区二区三区高清| 超碰在线免费观看97| 久久国产欧美日韩精品| 一区二区视频| 亚洲性生活网站| 欧美一级久久| 中文字幕一区不卡| 国产成人精品在线看| 最近中文字幕mv在线一区二区三区四区| 国产亚洲一区在线| 国产人妻一区二区| 亚洲综合在线一区二区| 看全色黄大色黄大片免责看的| 日韩久久一区二区三区| 青青草综合在线| 欧美电影免费网站| 欧美激情网友自拍| а√天堂www在线а√天堂视频| 日本中文字幕中出在线| 国产精品天美传媒| 国产精品欧美在线| 在线日韩av观看| 欧美成人中文字幕| 欧美xxxxxxxx| 亚洲一级生活片| 五月婷在线视频| 日本免费在线视频不卡一不卡二| 六十路精品视频| 在线免费高清一区二区三区| 久久96国产精品久久99软件| 在线丝袜欧美日韩制服| 欧美在线视频在线播放完整版免费观看| 五月婷婷色丁香| 电影天堂爱爱爱爱| 无人区乱码一区二区三区| 风流老熟女一区二区三区| 中文字幕日韩在线观看| 精品区一区二区| 一区二区高清不卡| 在线观看视频色潮| 深夜福利视频网站| 玖玖精品在线| 一起操在线播放| 国产av一区二区三区传媒| 亚洲xxxx在线| 美女一区二区久久| 中文字幕一二三区| 91www在线观看| 成人亚洲精品777777大片| 中午字幕在线观看| xvideos.蜜桃一区二区| 国模一区二区三区白浆| 韩国18福利视频免费观看| 午夜不卡久久精品无码免费| 日韩hmxxxx| 婷婷丁香综合| 国产精品一区二区三区不卡| www91在线观看| 亚洲欧美一二三| 国产四区在线观看| 欧州一区二区三区| 在线播放中文一区| 综合网插菊花| 国产欧美日本亚洲精品一4区| 一本色道久久88综合日韩精品| 亚洲国产精品久久久久秋霞不卡| 青青久在线视频| 亚洲欧美综合7777色婷婷| 精选一区二区三区四区五区| 精品美女久久久久| 欧美性受xxxx黑人猛交| 国产乱码77777777| 先锋影音二区| 久久精品日韩欧美| 国产在线视频欧美| 国产精品久久久久av福利动漫| 免费看黄色一级视频| 538任你躁在线精品免费| gogogo高清免费观看在线视频| 国产喷水theporn| 中文字幕国产精品一区二区| 亚洲一级一级97网| 亚洲黄色视屏| 色大师av一区二区三区| 99精品视频在线免费播放| 能在线观看的av| 国产精品最新自拍| 中文字幕中文字幕一区二区| 精品久久久免费视频| 一区二区不卡视频| 天天干,夜夜爽| 国产成人看片| 视频二区在线播放| 国产三级伦理在线| 亚洲婷婷在线视频| 精品久久久久一区二区| 国产熟女高潮一区二区三区| 欧美日韩麻豆| 日本在线视频www鲁啊鲁| 99tv成人影院| 这里只有精品免费视频| 亚洲熟妇无码另类久久久| 一区二区三区国产在线| 国产综合精品| 国产精品精品软件视频| 日本福利片在线观看| 精品孕妇一区二区三区| 国产精品作爱| 国产亚洲一区二区三区啪| 99综合99| 久久国产直播| 国产精品揄拍100视频| 久草视频一区二区| 精品99999| 无码aⅴ精品一区二区三区浪潮| 日韩av在线看免费观看| 1pondo在线播放免费| 青青青在线播放| 国产 日韩 欧美 综合| 亚洲影院天堂中文av色| 国精产品一区一区三区有限在线| 国产精品久久久久久久久久久久久久久久| 国产精品视频一二三| 中文字幕在线影院| 亚洲欧美韩国| 久久九九热视频| 成人三级网址| 我不卡伦不卡影院| 精品亚洲欧美一区| 波多野结衣高清视频| 欧美疯狂party性派对| 精品人妻一区二区三区换脸明星| 波多野洁衣一区| 美女在线视频免费| 波多野结衣黄色网址| 激情久久中文字幕| 欧美日韩国产综合视频在线观看中文| 伊人久久中文字幕| 最新中文字幕在线视频| 国产无码精品视频| 欧美性视频一区二区三区| 丰满熟女人妻一区二区三区| av大片免费在线观看| 色中文字幕在线观看| 欧美日韩国产专区| 两性午夜免费视频| 国产精品原创巨作av| 性xxxfreexxxx性欧美| eeuss影影院www在线播放| 亚洲日本久久久午夜精品| 日批在线观看视频| 在线亚洲色图| 制服诱惑亚洲| 亚洲欧洲日韩国产| 欧美日韩在线精品一区二区三区激情综合| 亚洲三级黄色在线观看| 欧美aaa免费|