條件變數的作用是用於多執行緒之間關於共享資料狀態變化的通訊。當乙個動作需要另外乙個動作完成時才能進行,即:當乙個執行緒的行為依賴於另外乙個執行緒對共享資料狀態的改變時,這時候就可以使用條件變數
假設沒有條件變數,對於乙個生產者消費者問題,消費執行緒在得知佇列中沒有產品時,將阻塞自己。生產線程給佇列中放入產品,但是沒有辦法啟用消費執行緒,而消費執行緒處於阻塞狀態也沒有辦法自啟用。如果消費執行緒使用忙等的方式,通過不斷地查詢來判斷是否有產品將大量的浪費cpu時間。消費執行緒可以使用睡眠+查詢的方式,即發現佇列中沒有產品時,sleep一段時間,然後再查詢。問題是睡眠多長時間?時間太長,實時性不好,時間太短,還是浪費cpu時間。
所以,通過生產線程通過喚醒消費執行緒時最好的方式。現在我們考慮一種實現,消費執行緒在阻塞之前要先解鎖,同時還要將自己的識別符號放入乙個地方,以便生產線程通過這個識別符號來啟用自己。這樣看起來是沒問題了,然而不要忘記了,執行緒之間是併發/並行的。消費執行緒可能剛完成解鎖的操作,就被生產線程獲取到了並開始執行,這時,因為消費執行緒還未掛起自己,來不及將自己的識別符號儲存在某個位置,所以生產線程不認為有正在等待的執行緒。這時,切換到消費執行緒後,消費執行緒將永遠的等待下去,雖然佇列中有產品。而生產線程因為佇列中有產品可能也一直的等待下去,形成了死鎖。
解決方法是必須讓解鎖、儲存執行緒識別符號、掛起這一系列操作成為原子操作。這中解決方案就是條件變數,所以不難想到使用條件變數的時候必須要「伴隨」乙個互斥量。
條件變數是與互斥量相關聯的一種用於多執行緒之間關於共享資料狀態改變的通訊機制。
它將解鎖和掛起封裝成為原子操作。等待乙個條件變數時,會解開與該條件變數相關的鎖,因此,使用條件變數等待的前提之一就是保證互斥量加鎖。執行緒醒來之後,該互斥量會被自動加鎖,所以,在完成相關操作之後需要解鎖。
條件變數總是和謂語相關,學過《離散數學》應該還記得謂語表示式吧。謂語是具有唯一真假值的句子。程式中,可以用謂語來描述當前執行緒需要的狀態。如果該謂語值為假,需要使用條件變數等待。醒來之後,由於系統的併發性,一般需要再次判斷謂語值是否為真,如果不為真,則再次使用條件變數進行等待。
互斥量是用來防止對不變數的破壞,換句話說,是用來規範執行緒對共享資料的競爭使用。而條件變數是用來對執行緒同步,即用來協調各個執行緒合作完成某個任務。比如:足球場上,兩個足球隊對乙個球的使用叫做競爭,可以使用「馬賽迴旋」這種「互斥量」對球加鎖,防止被搶。而傳球這個動作就是使用「條件變數」進行喚醒,它的作用是保證乙個球隊的各個成員能協作起來將球踢進對方的球門。
條件變數的關注物件是共享資料狀態的變化,這一變化可以使用謂語來描述。因為涉及到共享資料,所以需要互斥量。互斥量和條件變數的對應關係為1:n.就是說乙個互斥量可以對應多個條件變數,乙個條件變數只能對應乙個互斥量。這個可以這樣理解:因為共享資料有很多種狀態,描述這些狀態就需要多個謂語,所以需要用多個條件變數。
條件變數和謂語的對應關係一般最好為1:1、1:n或者n:1並不是不可以,但是容易引起死鎖和競爭問題,要特別注意。若1個條件變數對應於多個謂語時,喚醒應採用廣播的方式而不是signal的方式。
本文出自 「
相信並熱愛著
」 部落格,請務必保留此出處
條件變數基本概念和原理
條件變數的作用是用於多執行緒之間關於共享資料狀態變化的通訊。當乙個動作需要另外乙個動作完成時才能進行,即 當乙個執行緒的行為依賴於另外乙個執行緒對共享資料狀態的改變時,這時候就可以使用條件變數 假設沒有條件變數,對於乙個生產者消費者問題,消費執行緒在得知佇列中沒有產品時,將阻塞自己。生產線程給佇列中...
變數的基本概念
表示的資料是可以經常修改的,當乙個資料的值需要經常改變或者不確定時,就應該用變數來表示。定義變數,任何變數在使用前,必須先進行定義。目的 在記憶體中分配一塊儲存空間給變數,方便以後儲存資料 變數分為全域性變數和區域性變數。全域性變數定義在函式外部,程式開始到結束都一直在,而區域性變數定義在函式內部,...
網頁基本概念和工作原理
1.1 術語 客戶端 在計算機上執行並連線到網際網路的應用程式,如 chrome 或 firefox。其主要作用是進行使用者互動,並將其轉換為對另一台稱為 web 伺服器的計算機的請求。雖然我們通常使用瀏覽器訪問網路,但您可以將整個計算機視為客戶端 伺服器模型的客戶端。每個客戶端計算機都有乙個唯一的...