條件變量的做用是用於多線程之間關於共享數據狀態變化的通訊。當一個動做須要另一個動做完成時才能進行,即:當一個線程的行爲依賴於另一個線程對共享數據狀態的改變時,這時候就可使用條件變量多線程
因此,經過生產線程經過喚醒消費線程時最好的方式。如今咱們考慮一種實現,消費線程在阻塞以前要先解鎖,同時還要將本身的標識符放入一個地方,以便生產線程經過這個標識符來激活本身。這樣看起來是沒問題了,然而不要忘記了,線程之間是併發/並行的。消費線程可能剛完成解鎖的操做,就被生產線程獲取到了並開始執行,這時,由於消費線程還未掛起本身,來不及將本身的標識符保存在某個位置,因此生產線程不認爲有正在等待的線程。這時,切換到消費線程後,消費線程將永遠的等待下去,雖然隊列中有產品。而生產線程由於隊列中有產品可能也一直的等待下去,造成了死鎖。
解決方法是必須讓解鎖、保存線程標識符、掛起這一系列操做成爲原子操做。這中解決方案就是條件變量,因此不難想到使用條件變量的時候必需要「伴隨」一個互斥量。
條件變量是與互斥量相關聯的一種用於多線程之間關於共享數據狀態改變的通訊機制。它將解鎖和掛起封裝成爲原子操做。等待一個條件變量時,會解開與該條件變量相關的鎖,所以,使用條件變量等待的前提之一就是保證互斥量加鎖。線程醒來以後,該互斥量會被自動加鎖,因此,在完成相關操做以後須要解鎖。
條件變量老是和謂語相關,學過《離散數學》應該還記得謂語表達式吧。謂語是具備惟一真假值的句子。程序中,能夠用謂語來描述當前線程須要的狀態。若是該謂語值爲假,須要使用條件變量等待。醒來以後,因爲系統的併發性,通常須要再次判斷謂語值是否爲真,若是不爲真,則再次使用條件變量進行等待。
互斥量是用來防止對不變量的破壞,換句話說,是用來規範線程對共享數據的競爭使用。而條件變量是用來對線程同步,即用來協調各個線程合做完成某個任務。好比:足球場上,兩個足球隊對一個球的使用叫作競爭,可使用「馬賽迴旋」這種「互斥量」對球加鎖,防止被搶。而傳球這個動做就是使用「條件變量」進行喚醒,它的做用是保證一個球隊的各個成員能協做起來將球踢進對方的球門。
條件變量的關注對象是共享數據狀態的變化,這一變化可使用謂語來描述。由於涉及到共享數據,因此須要互斥量。互斥量和條件變量的對應關係爲1:N.就是說一個互斥量能夠對應多個條件變量,一個條件變量只能對應一個互斥量。這個能夠這樣理解:由於共享數據有不少種狀態,描述這些狀態就須要多個謂語,因此須要用多個條件變量。
條件變量和謂語的對應關係通常最好爲1:1.1:N或者N:1並非不能夠,可是容易引發死鎖和競爭問題,要特別注意。若1個條件變量對應於多個謂語時,喚醒應採用廣播的方式而不是signal的方式。