基於條件變數阻塞pthread cond wait

2021-06-28 10:48:13 字數 4026 閱讀 2836

使用 pthread_cond_wait(3c) 可以以原子方式釋放 mp 所指向的互斥鎖,並導致呼叫執行緒基於 cv 所指向的條件變數阻塞。對於 solaris 執行緒,請參見cond_wait 語法。

int	pthread_cond_wait(pthread_cond_t *cv,pthread_mutex_t *mutex);
#include pthread_cond_t cv;

pthread_mutex_t mp;

int ret;

/* wait on condition variable */

ret = pthread_cond_wait(&cv, &mp);

阻塞的執行緒可以通過 pthread_cond_signal()

或 pthread_cond_broadcast()

喚醒,也可以在訊號傳送將其中斷時喚醒。

不能通過 pthread_cond_wait()

的返回值來推斷與條件變數相關聯的條件的值的任何變化。必須重新評估此類條件。

pthread_cond_wait()

例程每次返回結果時呼叫執行緒都會鎖定並且擁有互斥鎖,即使返回錯誤時也是如此。

該條件獲得訊號之前,該函式一直被阻塞。該函式會在被阻塞之前以原子方式釋放相關的互斥鎖,並在返回之前以原子方式再次獲取該互斥鎖。

通常,對條件表示式的評估是在互斥鎖的保護下進行的。如果條件表示式為假,執行緒會基於條件變數阻塞。然後,當該執行緒更改條件值時,另乙個執行緒會針對條件變數發出訊號。這種變化會導致所有等待該條件的執行緒解除阻塞並嘗試再次獲取互斥鎖。

必須重新測試導致等待的條件,然後才能從 pthread_cond_wait()

處繼續執行。喚醒的執行緒重新獲取互斥鎖並從 pthread_cond_wait()

返回之前,條件可能會發生變化。等待執行緒可能並未真正喚醒。建議使用的測試方法是,將條件檢查編寫為呼叫 pthread_cond_wait()

的 while()

迴圈。

pthread_mutex_lock();

while(condition_is_false)

pthread_cond_wait();

pthread_mutex_unlock();

如果有多個執行緒基於該條件變數阻塞,則無法保證按特定的順序獲取互斥鎖。

注 –pthread_cond_wait()

是取消點。如果取消處於暫掛狀態,並且呼叫執行緒啟用了取消功能,則該執行緒會終止,並在繼續持有該鎖的情況下開始執行清除處理程式。

pthread_cond_wait()

在成功完成之後會返回零。其他任何返回值都表示出現了錯誤。如果出現以下情況,該函式將失敗並返回對應的值。

einval

描述:cv 或 mp 指定的值無效。

對於基於 cv 所指向的條件變數阻塞的執行緒,使用 pthread_cond_signal(3c) 可以解除阻塞該執行緒。對於 solaris 執行緒,請參見cond_signal 語法。

int	pthread_cond_signal(pthread_cond_t *cv);
#include pthread_cond_t cv;

int ret;

/* one condition variable is signaled */

ret = pthread_cond_signal(&cv);

應在互斥鎖的保護下修改相關條件,該互斥鎖用於獲得訊號的條件變數中。否則,可能在條件變數的測試和 pthread_cond_wait()

阻塞之間修改該變數,這會導致無限期等待。

排程策略可確定喚醒阻塞執行緒的順序。對於 sched_other,將按優先順序順序喚醒執行緒。

如果沒有任何執行緒基於條件變數阻塞,則呼叫 pthread_cond_signal()

不起作用。

示例 4–8 使用 pthread_cond_wait()

和 pthread_cond_signal()

pthread_mutex_t count_lock;

pthread_cond_t count_nonzero;

unsigned count;

decrement_count()

increment_count()

pthread_cond_signal()

在成功完成之後會返回零。其他任何返回值都表示出現了錯誤。如果出現以下情況,該函式將失敗並返回對應的值。

einval

描述:cv 指向的位址非法。

示例 4–8 說明了如何使用 pthread_cond_wait()

和 pthread_cond_signal()

。pthread_cond_timedwait(3c) 的用法與 pthread_cond_wait()

的用法基本相同,區別在於在由 abstime 指定的時間之後pthread_cond_timedwait()

不再被阻塞。

int	pthread_cond_timedwait(pthread_cond_t *cv,

pthread_mutex_t *mp, const struct timespec *abstime);

#include #include pthread_cond_t cv;

pthread_mutex_t mp;

timestruct_t abstime;

int ret;

/* wait on condition variable */

ret = pthread_cond_timedwait(&cv, &mp, &abstime);

pthread_cond_timewait()

每次返回時呼叫執行緒都會鎖定並且擁有互斥鎖,即使 pthread_cond_timedwait()

返回錯誤時也是如此。 對於 solaris 執行緒,請參見cond_timedwait 語法。

pthread_cond_timedwait()

函式會一直阻塞,直到該條件獲得訊號,或者最後乙個引數所指定的時間已過為止。

注 –pthread_cond_timedwait()

也是取消點。

示例 4–9 計時條件等待

pthread_timestruc_t to;

pthread_mutex_t m;

pthread_cond_t c;

...pthread_mutex_lock(&m);

to.tv_sec = time(null) + timeout;

to.tv_nsec = 0;

while (cond == false)

}pthread_mutex_unlock(&m);

pthread_cond_timedwait()

在成功完成之後會返回零。其他任何返回值都表示出現了錯誤。如果出現以下任一情況,該函式將失敗並返回對應的值。

einval

描述:cv 或 abstime 指向的位址非法。

etimedout

描述:abstime 指定的時間已過。

超時會指定為當天時間,以便在不重新計算值的情況下高效地重新測試條件,如示例 4–9 中所示。

pthread條件變數深入解析

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

基於陣列實現阻塞佇列

基於陣列實現的話,需要額外兩個指標,乙個指向頭元素,乙個指向尾元素。出的時候從頭元素出去,入的時候從尾元素入。即出的時候tail指標 1,入的時候尾指標 1 因此使用乙個環形佇列最好,不會浪費空間也不需要挪動元素位置。因為是環形佇列,因此tail在最後乙個位置的時候,再進來乙個元素,如果佇列不滿,就...

條件變數 pthread cond init

include int pthread cond init pthread cond t cv,const pthread condattr t cattr 返回值 函式成功返回0 任何其他返回值都表示錯誤初始化乙個條件變數。當引數cattr為空指標時,函式建立的是乙個預設的條件變數。否則條件變數的...