Linux 同步 條件變數

2021-10-02 20:33:32 字數 1740 閱讀 5171

我們知道互斥是為了保證每次只能有乙個執行流訪問臨界資源。接下來我們看看為什麼還需要同步?

同步是為了保證執行流訪問臨界資源的合理性。也就是說當沒有臨界資源了,讓執行流(消費者)進行等待,等待另乙個執行流(生產者)來生產乙個臨界資源,之後再喚醒剛才進入等待的執行流進行訪問資源。

舉個例子現在有乙個全域性變數g_val=0,但是有乙個執行流a想對g_val進行-1操作,因為臨界資源此時為0,所以讓a先進入等待,直到另乙個執行流b對臨界資源g_val進行+1操作,此時臨界資源g_val為1,b才能喚醒a去拿互斥鎖,對g_val進行操作。

那麼同步是怎麼實現的呢?這就必須用到條件變數

條件變數提供了兩個介面(等待介面、喚醒介面)和乙個pcb等待佇列

條件變數的介面:

1.定義條件變數:

pthread_cond_t con;

2.條件變數初始化:

(1)pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *attr);

cond:傳入條件變數的位址。

attr:傳入條件變數的屬性,通常傳入null,預設屬性。

(2)pthread_cond_t con=pthread_cond_initializer;

3.等待介面:

pthread_cond_wait (pthread_cond_t *cond,pthread_mutex_t *mutex);這裡大家可能有疑問了,條件變數是實現同步的,那麼為什麼要用到互斥變數呢?

因為條件變數只保證了同步,但是各個執行流之間的衝突還是存在的,也是有可能造成程式的二義性。

舉個例子來理解一下:

若此時臨界資源g_val為0,那麼當有消費執行緒訪問g_val發現沒有可用資源,就會呼叫等待介面把pcb放到等待佇列中等待生產線程生產g_val。如果生產了乙個資源,此時就會喚醒等待佇列中的消費執行緒來消費,因為等待的不止乙個執行緒,所以這些執行緒被喚醒時,不可能同時訪問g_val,還是需要先獲取互斥鎖,才能訪問g_val。

那麼問題又來了,這個等待介面中是如何使用互斥鎖的呢?

當執行緒呼叫了等待介面後,此時呼叫介面的執行緒陷入阻塞狀態。

等待介面內部操作分為三步:

(1)將執行緒pcb放到pcb等待佇列中去。

(2)釋放互斥鎖。

(3)被生產線程從pcb等待佇列中喚醒,爭奪鎖資源。爭奪到了訪問臨界資源,否則無法訪問臨界資源,繼續呼叫等待介面。

4.喚醒介面

pthread_cond_signal(pthread_cond_t* cond);pthread_cond_broadcast(pthread_cond_t* cond);

喚醒pcb等待佇列裡的全部等待執行緒。

5.摧毀條件變數

pthread_cond_destroy(pthread_cond_t* cond)

同步的實現**

Linux執行緒同步 條件變數

執行緒間的同步還有乙個情況 程序a 需要等待乙個條件成立,才執行,當條件不成立時就阻塞等待 程序b 需要設定條件,當條件成立時,喚醒程序a.這裡我們就可以用到條件變數。條件變數變數也是出自posix執行緒標準,另一種執行緒同步機制,主要用來等待某個條件的發生,然後進行相應的操作,這樣可以消除多執行緒...

Linux 執行緒同步 條件變數

pthread cond signal 使在條件變數上等待的執行緒中的乙個執行緒重新開始。如果沒有等待的執行緒,則什麼也不做。如果有多個執行緒在等待該條件,只有乙個能重啟動,但不能指定哪乙個。pthread cond broadcast 重啟動等待該條件變數的所有執行緒。如果沒有等待的執行緒,則什麼...

Linux執行緒同步之條件變數

與互斥鎖不同,條件變數是用來等待而不是用來上鎖的。條件變數用來自動阻塞乙個執行緒,直到某特殊情況發生為止。通常條件變數和互斥鎖同時使用。條件變數使我們可以睡眠等待某種條件出現。條件變數是利用執行緒間共享的全域性變數進行同步的一種機制,主要包括兩個動作 乙個執行緒等待 條件變數的條件成立 而掛起 另乙...