pthread條件變數深入解析

2021-09-14 00:45:02 字數 1781 閱讀 9049

用條件變數實現事件等待器的正確與錯誤做法 提到了8種 基於 linux pthread 條件變數實現的 waiter classes,並分析了幾種錯誤實現的錯誤之處。本文進一步分析一下幾種正確實現的程式行為,加深對linux pthread 條件變數的理解。

下面給出乙個可以用於single waiter的waiterclass的正確實現。

class waiter : private waiterbase

check_success(pthread_mutex_unlock(&mutex_));

} void signal()

private:

bool signaled_ = false;

};

要實現乙個正確的waiter class, 由 1 可知 wait() 函式的指令順序必須如上所示。但signal() 函式可以有幾種不同的實現,即**行 1,2,3可以有幾種不同的順序組合,使得waiter class是正確的。這幾種組合包括了1 給出的幾種正確實現。

首先對 **行1,2,3 給出所有可能的排列形式,然後一一說明其是否正確。

a. 1-2-3

b. 1-3-2

c. 2-1-3

d. 2-3-1

e. 3-1-2

f. 3-2-1

要分析以上6種實現的對錯,先要了解一下 pthread_cond_wait 和 pthread_cond_signal 的內部流程。

假設等待訊號的執行緒為a,發出訊號的執行緒為b。

執行緒a,pthread_cond_wait()內部包括以下流程:

將 waiter 加入cond 的 _wseq 佇列 (分為g1 g2兩個組)

釋放mutex

自旋等待,檢查 __g_signals,自旋次數結束,進入 futex_wait,休眠

執行緒b,pthread_cond_signal()包括以下流程:

檢查 cond __wseq,若沒有等待者則直接返回。

有等待者,檢查是否需要切換組(例如首次呼叫 wait 後 g1 為空,g2有乙個等待者,則首次呼叫 signal 後需要將 g2 切換為 g1),遞增 __g_signals,遞減 __g_size(未喚醒的 waiters 個數),再呼叫 futex_wake。

signal 將一直喚醒g1組的 waiters 直到 g1 所有的 waiters 都被喚醒。若此過程種有新到達的waiter, 則存入g2 組(之後到達的 waiter 也存入g2)。g2組會在下次signal 呼叫時轉為g1組,因此signal永遠只喚醒g1 組的 waiters。(參考)

有了以上的細節,可以很容易的得出問題的結論。

首先應當排除e和f。ef拿到鎖又馬上釋放鎖,1和2都不被鎖保護,1,2執行的時機可以任意穿插到wait()函式各語句zhi'jian,從而語句2發出的訊號很可能會丟失

d也是錯誤的。一種導致執行緒a餓死的時序:2發訊號,喚醒執行緒a,3釋放鎖,a獲得鎖,判斷布林值,條件為真,再次進入等待,一直休眠

ac是正確的。不管發訊號時是否修改了布林值,被喚醒的a執行緒始終無法得到mutex,直到3釋放鎖,futex_wake通知執行緒a, a才可以拿到鎖,從pthread_cond_wait返回,繼續向下執行,此時布林值已經改變,條件測試為假,跳出迴圈,繼續執行。事實上,由於編譯器亂序和cpu 亂序,ac有可能執行的次序是相同的。

b也是正確的。b執行緒在修改布林變數後釋放鎖,此時執行緒a依然處在休眠狀態,不知道發生的一切,只有當b發訊號喚醒a時,a才可以看到這一切,成功獲得鎖,進而繼續向下執行。

總結發現,只要布林值的修改是在釋放鎖的操作之前,就能保證其正確性。

JBPM深入解析之變數設計

jbpm深入解析之變數設計 在流程的流轉的過程中,很多時候我們需要根據不同的實際情況傳入一些初始化資料,以便完成我們個性化的業務需求 同時很多時候我們需要在不同的節點之間共享一些業務資料,特別是一些節點要以前一節點的輸出作為輸入等 變數對於流程引擎來說很重要,可以說沒有變數,那麼我們就不能執行時動態...

深入理解條件變數 虛假喚醒

深入條件變數 pthread cond wait 和pthread cond signal 的偽實現 pthread cond wait mutex,cond 競爭失敗,那麼就不加入等待佇列了,相當於直接 喚醒 else pthread mutex unlock cond mutex 重新鎖住傳入的...

多執行緒中條件變數使用的深入剖析

參考部落格 之前一直以為條件變數在pthread cond wait時會一直持有互斥量,後來看到陳碩的書上的例子,發現如果是這樣會很容易造成死鎖,因此才考慮到是自己想錯了,於是在網上搜尋了資料終於弄明白了是怎麼回事 第一點 條件變數在pthread cond wait狀態不持有互斥鎖 條件變數進入p...