2018年8月6日 星期一

multithread: Condition Variables

在 multi-thread 程式,mutex 用來避免同時存取共用變數而造成衝突,但 thread 有時需要看共用變數狀態改變了才進行處理,需要類似如下步驟的無窮迴圈:
  1. 鎖住共用變數的 mutex
  2. 共用變數是想要的狀態則進行處理
  3. 解鎖 mutex
步驟 2 共用變數的狀態常常不是想要的,而忙於一直進行無意義的 mutex 鎖住和解鎖 (步驟 1→3)。上述例子是一個進行處理的 consumer,另外有其它 producer thread 產生需要處理的狀態。condition variable 讓 consumer 先去休息,直到 producer 通知狀態改變了才喚醒進行處理,不用忙於 mutex 鎖住和解鎖的迴圈:
  1. 鎖住共用變數的 mutex
  2. 共用變數不是想要的狀態則休息直到等候到 condition variable 才進行處理
  3. 解鎖 mutex
等候 condition variable 需要搭配檢查共用變數的狀態,也就是需要搭配共用變數的 mutex,而等候 condition variable 的函數內部需要暫時解鎖 mutex,讓其它 thread 可以改變共用變數,所以稍後在等候 condition variable 的函數可以看到需要傳遞搭配的 mutex。

初始化及銷毀

#include <pthread.h>

condition variable 必須初始化之後才能使用,不能複製。例如靜態配置:
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
或動態配置:
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
condition variable 沒有 consumer 等候才能銷毀。
int pthread_cond_destroy(pthread_cond_t *cond);

Consumer 進入等候

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
等待 cond,呼叫前必須先鎖住 mutex。也確保收到通知後是鎖住的。一般等候結束後,需要再檢查共享變數的狀態是不是想要的,特別是:
  1. 有多個 consumer,不能確定哪個被喚醒。
  2. 有時候應用程式設計成狀態可能發生比必定發生容易。
  3. 有可能出現假的喚醒 (Spurious  wakeup)。在有些多處理器系統的實作,為了效率而罕見地出現,這是 SUSv3 所允許的。

如果等候時間有上限:
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
引數 abstime 是 timespec (TLPI §23.4.2),為從 Epoch (TLPI §10.1) 開始的絕對時間 ( seconds 和 nano seconds)。到期回 ETIMEDOUT。

Producer 通知結束等候

依據排程讓其中一個 thread 結束等候
int pthread_cond_signal(pthread_cond_t *cond);

全部結束等候

int pthread_cond_broadcast(pthread_cond_t *cond);

如果當下沒有 thread 等候,通知就失去作用,不會延遲給後續的等候。一般來講,先解鎖相關的 mutex 後再通知效能較好。

參考

  1. TLPI §30.2 §30.2.1 §30.2.2 §30.2.3 §30.2.5
  • uClibc condattr 沒作用,沒有 pthread_condattr_setclock()。
  • uClibc v0.9.31 pthread_cond_timedwait() 用 timedsuspend() 等候 abstime。而 timedsuspend() 內部是用 nanosleep() 等候相對時間。

沒有留言:

張貼留言

SIP header Via

所有 SIP 訊息 都要有 Via,縮寫 v。一開始的 UAC 和後續途經的每個 proxy 都會疊加一個 Via 放傳送的位址,依序作為回應的路徑。 格式 sent-protocol sent-by [ ;branch= branch ][ ; 參數 ...] s...