程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> pthread

pthread

編輯:關於C語言
 

虛假喚醒

最近在使用Linux條件變量的時候,經過反復測試發現,pthread_cond_signal有時候會喚起多個正在pthread_cond_wait的線程。後來通過查閱IEEE Std 1003.1, 2004中關於pthread_cond_signal虛假喚醒(spurious wakeup)的解釋如下:


On a multi-processor, it may be impossible for an implementation of pthreadcondsignal() to avoid the unblocking of more than one thread blocked on a condition variable.

根據這個解釋,在多處理器系統上,pthread_cond_signal是很有可能喚醒多個pthread_cond_wait()的線程。也就意味著當一個線程中,pthread_cond_wait()返回的時候,不一定代表條件已經滿足了,需要在程序中做額外的判斷來檢測是否真的已經滿足條件了:

1 pthread_mutex_lock(&lock);
2 while (condition_is_false) {
3 pthread_cond_wait(&cond, &lock);
4 }
5 pthread_mutex_unlock(&lock);

事實上,IEEE Std 1003.1, 2004中有提到,虛假喚醒(spurious wakeup)是被允許的,而且鼓勵程序開發者在pthread_cond_wait()返回的時候對條件進行重新檢查,只有在條件滿足的情況下才繼續往下執行,否則就需要繼續等待了。

關於多處理器系統出現虛假喚醒(sprious wakeup)的原因,我的理解是因為多處理器上,多線程共享的數據需要在多核處理器上cache進行更新和拷貝的原因。關於多核多線程請參考《利用多核多線程進行程序優化》

消息遺漏

對於pthread_cond_signal或者pthread_cond_broadcast來說,除了需要在pthread_cond_wait()返回的時候,重新對條件進行檢查和評估以外,還有一件事情就是需要解決消息遺漏的問題。

根據pthread_cond_wait的定義,需要在pthread_cond_wait調用前後必須進行加鎖和解鎖操作。原因是因為如果在一個線程調用pthread_cond_wait的過程中但未進入block狀態,此時有線程調用了pthread_cond_signal或者pthread_cond_broadcast,那麼此次消息將被遺漏掉,因為沒有任何線程在pthread_cond_wait的block狀態。在pthread_cond_wait的實現內部,首先會解鎖,然後進入block狀態,解鎖和進入block必須合並成一個原子操作,這樣就保證了在pthread_cond_wait之後調用的pthread_cond_signal不會被以後掉。

但是對於多線程來說,pthread_cond_wait不能保證一定在pthread_cond_signal之後執行,也就意味著,當pthread_cond_wait進入block之後,已經錯過了pthread_cond_signal。因為已經錯過了pthread_cond_signal,很有可能會導致該線程永遠block下去。通常這類問題的解決辦法是設置一個pthread_cond_signal或者pthread_cond_broadcast的計數器count,在調用pthread_cond_wait之前先對這個count進行判斷,如果count != 0 則說明已經錯過了消息,可以不用等待,直接往下執行即可:

1 if (!count) {
2 pthread_mutex_lock(&lock);
3 while (condition_is_false) {
4 pthread_cond_wait(&cond, &lock);
5 }
6 pthread_mutex_unlock(&lock);
7 }
 

 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved