條件變量:為什么要與互斥鎖配套使用?為什么要使用while來避免虛假喚醒?


首先關於條件變量的引入:

假想在這樣的情況下,多個線程需要等待某個條件才能繼續工作(如生產者消費者模型中,消費者需要等待流水線上有產品后才能消費),如果只使用互拆鎖,則多個線程要不停的查詢流水線是否為空這個狀態,並且查詢這個操作需要加入臨界區,因為流水線不僅同時有多個消費者,還有生產者在生產,不加鎖的話可能出現兩個甚至多個消費者對同一個產品動手的情況。這種不停查詢的操作是很蠢的,因此引入了條件變量,在查詢條件不滿足的情況下線程休眠,讓出CPU。

為什么要傳入互斥鎖,與互斥鎖配套使用?

首先,條件本身就是公共資源,如流水線的狀態,因此必須使用互斥鎖在臨界區內對條件進行保護。

其次,pthread_cond_wait()操作實際上分為兩步,第一步將線程掛在等待條件的線程列表上,然后對互斥鎖解鎖。

如果不傳入這個互斥鎖,實際上流程變為:

1.加鎖

2.判斷流水線狀態

3.解鎖

4.掛起線程

則在3與4間非原子,如果在3之后生產者線程生產了一個產品並進行了notify,而notify結束后這個消費者線程才掛起,則這個notify丟失了,只有生產者再生產一個產品才會喚醒它,如果只有一個消費者的話則這個notify完全丟失,如果有多個消費者則還可能被其他消費者所捕獲,但邏輯上出現了問題。

為什么會出現虛假喚醒,為什么要用while來避免虛假喚醒?

虛假喚醒的出現在於生產者的notify並不在臨界區內,也就是說,生產者使用臨界區保護了修改流水線的這個操作,然后解鎖,解鎖完畢后才notify。而在這之間是非原子的。

在以下情況:

1).生產者對臨界區加鎖

2).修改流水線狀態

3).生產者解鎖

4).notify通知生產者線程

在3)與4)間是有空隙的,如果在3)進行后突然此刻加入了一個新的生產者,這個生產者察覺到流水線的變化,對他進行了消費,然后消費者才notify,notify喚醒了原有的消費者, 但流水線已經為空了,實際上這就是一個虛假喚醒,喚醒后並無工作可做。

因此不能用if來進行條件判斷,加入while就可以避免虛假喚醒,在每次喚醒后先判斷流水線條件,這樣避免了虛假喚醒的情況。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM