真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

使用條件變量的坑有哪些

本篇內(nèi)容介紹了“使用條件變量的坑有哪些”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

遂平ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書(shū)未來(lái)市場(chǎng)廣闊!成為創(chuàng)新互聯(lián)的ssl證書(shū)銷售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:13518219792(備注:SSL證書(shū)合作)期待與您的合作!

1. 什么是條件變量?

條件變量是多線程程序中用來(lái)實(shí)現(xiàn)等待和喚醒邏輯常用的方法。通常有wait和notify兩個(gè)動(dòng)作,wait用于阻塞掛起線程A,直到另一個(gè)線程B通過(guò)通過(guò)notify喚醒線程A,喚醒后線程A會(huì)繼續(xù)運(yùn)行。

條件變量在多線程中很常用,在有名的生產(chǎn)者和消費(fèi)者問(wèn)題中,消費(fèi)者如何知道生成者是否生產(chǎn)出了可以消費(fèi)的產(chǎn)品,通過(guò)while循環(huán)不停的去判斷是否有可消費(fèi)的產(chǎn)品?眾所周知,死循環(huán)極其消耗CPU性能,所以需要使用條件變量來(lái)阻塞線程,降低CPU占用率。

2. 條件變量的使用

拿生產(chǎn)者和消費(fèi)者問(wèn)題舉例,看下面這段代碼:

std::mutex mutex; std::condition_variable cv; std::vector vec;  void Consume() {   std::unique_lock lock(mutex);   cv.wait(lock);   std::cout << "consume " << vec.size() << "\n"; }  void Produce() {   std::unique_lock lock(mutex);   vec.push_back(1);   cv.notify_all();   std::cout << "produce \n"; }  int main() {   std::thread t(Consume);   t.detach();   Produce();   return 0; }

本意是消費(fèi)者線程阻塞,等待生產(chǎn)者生產(chǎn)數(shù)據(jù)后去通知消費(fèi)者線程,這樣消費(fèi)者線程就可以拿到數(shù)據(jù)去消費(fèi)。

但這里有個(gè)問(wèn)題:

如果先執(zhí)行的Produce(),后執(zhí)行的Consume(),生產(chǎn)者提前生產(chǎn)出了數(shù)據(jù),去通知消費(fèi)者,但是此時(shí)消費(fèi)者線程如果還沒(méi)有執(zhí)行到wait語(yǔ)句,即線程還沒(méi)有處于掛起等待狀態(tài),線程沒(méi)有等待此條件變量上,那通知的信號(hào)就丟失了,后面Consume()中才執(zhí)行wait處于等待狀態(tài),但此時(shí)生產(chǎn)者已經(jīng)不會(huì)再觸發(fā)notify,那消費(fèi)者線程就會(huì)始終阻塞下去,出現(xiàn)bug。

如何解決這個(gè)問(wèn)題呢?可以附加一個(gè)判斷條件,就可以解決這種信號(hào)丟失問(wèn)題,見(jiàn)代碼:

std::mutex mutex; std::condition_variable cv; std::vector vec;  void Consumer() {   std::unique_lock lock(mutex);   if (vec.empty()) { // 加入此判斷條件       cv.wait(lock);   }   std::cout << "consumer " << vec.size() << "\n"; }  void Produce() {   std::unique_lock lock(mutex);   vec.push_back(1);   cv.notify_all();   std::cout << "produce \n"; }  int main() {   std::thread t(Consumer);   t.detach();   Produce();   return 0; }

通過(guò)增加附加條件可以解決信號(hào)丟失的問(wèn)題,但這里還有個(gè)地方需要注意,消費(fèi)者線程處于wait阻塞狀態(tài)時(shí),即使沒(méi)有調(diào)用notify,操作系統(tǒng)也會(huì)有一些概率會(huì)喚醒處于阻塞的線程,使其繼續(xù)執(zhí)行下去,這就是虛假喚醒問(wèn)題,當(dāng)出現(xiàn)了虛假喚醒后,消費(fèi)者線程繼續(xù)執(zhí)行,還是沒(méi)有可以消費(fèi)的數(shù)據(jù),出現(xiàn)了bug。

那怎么解決虛假喚醒的問(wèn)題呢,可以在線程由阻塞狀態(tài)被喚醒后繼續(xù)判斷附加條件,看是否滿足喚醒的條件,如果滿足則繼續(xù)執(zhí)行,如果不滿足,則繼續(xù)去等待,體現(xiàn)在代碼中,即將if判斷改為while循環(huán)判斷,見(jiàn)代碼:

std::mutex mutex; std::condition_variable cv; std::vector vec;  void Consumer() {   std::unique_lock lock(mutex);   while (vec.empty()) { // 將if改為while       cv.wait(lock);   }   std::cout << "consumer " << vec.size() << "\n"; }  void Produce() {   std::unique_lock lock(mutex);   vec.push_back(1);   cv.notify_all();   std::cout << "produce \n"; }  int main() {   std::thread t(Consumer);   t.detach();   Produce();   return 0; }

看到這里相信你已經(jīng)明白條件變量的使用啦,需要使用while循環(huán)附加判斷條件來(lái)解決條件變量的信號(hào)丟失和虛假喚醒問(wèn)題。

3. 有沒(méi)有更簡(jiǎn)單的“避坑”方式

難道我們每次都必須要使用while循環(huán)和附加條件來(lái)操作條件變量嗎?這豈不是很麻煩?

NO!

在C++中其實(shí)有更好的封裝,只需要調(diào)用wait函數(shù)時(shí),在參數(shù)中直接添加附加條件就好了,內(nèi)部已經(jīng)做好了while循環(huán)判斷,直接使用即可,見(jiàn)代碼:

std::mutex mutex; std::condition_variable cv; std::vector vec;  void Consumer() {   std::unique_lock lock(mutex);   cv.wait(lock, [&](){ return !vec.empty(); }); // 這里可以直接使用C++的封裝   std::cout << "consumer " << vec.size() << "\n"; }  void Produce() {   std::unique_lock lock(mutex);   vec.push_back(1);   cv.notify_all();   std::cout << "produce \n"; }  int main() {   std::thread t(Consumer);   t.detach();   Produce();   return 0; }

但在C語(yǔ)言中就沒(méi)辦法啦,大家只能自己做一層封裝啦。

4. 為什么條件變量需要和鎖配合使用?

為什么叫條件變量呢?

因?yàn)閮?nèi)部是通過(guò)判斷及修改某個(gè)全局變量來(lái)決定線程的阻塞與喚醒,多線程操作同一個(gè)變量肯定需要加鎖來(lái)使得線程安全。同時(shí),一個(gè)簡(jiǎn)單的wait函數(shù)調(diào)用內(nèi)部會(huì)很復(fù)雜的,有可能線程A調(diào)用了wait函數(shù)但是還沒(méi)有進(jìn)入到wait阻塞等待前,另一個(gè)線程B在此時(shí)卻調(diào)用了notify函數(shù),此時(shí)nofity的信號(hào)就丟失啦,如果加了鎖,線程B必須等待線程A釋放了鎖并進(jìn)入了等待狀態(tài)后才可以調(diào)用notify,繼而防止信號(hào)丟失。

關(guān)于條件變量就介紹到這里,希望大家能有所收獲,平時(shí)使用過(guò)程中可以避掉條件變量的坑。

“使用條件變量的坑有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!


分享標(biāo)題:使用條件變量的坑有哪些
網(wǎng)址分享:http://weahome.cn/article/ipggdj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部