閱讀301 返回首頁    go 阿裏雲 go 技術社區[雲棲]


linux線程同步之條件變量

    條件變量通過允許線程阻塞和等待另一個線程發送信號的方法彌補了互斥鎖的不足,它常和互斥鎖一起使用。使用時,條件變量被用來阻塞一個線程,當條件不滿足時,線程往往解開相應的互斥鎖並等待條件發生變化。一旦其它的某個線程改變了條件變量,它將通知相應的條件變量喚醒一個或多個正被此條件變量阻塞的線程。這些線程將重新鎖定互斥鎖並重新測試條件是否滿足。一般說來,條件變量被用來進行線承間的同步。
 
1.條件變量的結構為pthread_cond_t (相當於windows中的事件的作用)
 
2.條件變量的初始化
      int pthread_cond_init __P ((pthread_cond_t *__cond,__const pthread_condattr_t *__cond_attr));
  其中cond是一個指向結構pthread_cond_t的指針,cond_attr是一個指向結構pthread_condattr_t的指針。結構 pthread_condattr_t是條件變量的屬性結構,和互斥鎖一樣我們可以用它來設置條件變量是進程內可用還是進程間可用,默認值是 PTHREAD_ PROCESS_PRIVATE,即此條件變量被同一進程內的各個線程使用。注意初始化條件變量隻有未被使用時才能重新初始化或被釋放。
 

條件變量和互斥鎖一樣,都有靜態動態兩種創建方式,靜態方式使用PTHREAD_COND_INITIALIZER常量,如下:

pthread_cond_t cond=PTHREAD_COND_INITIALIZER

動態方式調用pthread_cond_init()函數,API定義如下:

int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr)
盡管POSIX標準中為條件變量定義了屬性,但在LinuxThreads中沒有實現,因此cond_attr值通常為NULL,且被忽略。
3.條件變量的釋放
釋放一個條件變量的函數為pthread_cond_ destroy(pthread_cond_t cond)
 
4.條件變量的等待
      (1)函數pthread_cond_wait()使線程阻塞在一個條件變量上。它的函數原型為:
  extern int pthread_cond_wait_P ((pthread_cond_t *__cond,pthread_mutex_t *__mutex));
  線程解開mutex指向的鎖並被條件變量cond阻塞。線程可以被函數pthread_cond_signal和函數 pthread_cond_broadcast喚醒,但是要注意的是,條件變量隻是起阻塞和喚醒線程的作用,具體的判斷條件還需用戶給出,例如一個變量是否為0等等,這一點我們從後麵的例子中可以看到。線程被喚醒後,它將重新檢查判斷條件是否滿足,如果還不滿足,一般說來線程應該仍阻塞在這裏,被等待被下一次喚醒。這個過程一般用while語句實現。
  (2)另一個用來阻塞線程的函數是pthread_cond_timedwait(),它的原型為:
  extern int pthread_cond_timedwait_P (pthread_cond_t *__cond,
                                                                    pthread_mutex_t *__mutex, __const struct timespec *__abstime);
  它比函數pthread_cond_wait()多了一個時間參數,經曆abstime段時間後,即使條件變量不滿足,阻塞也被解除。

5.條件變量的解除改變
      函數pthread_cond_signal()的原型為:
  extern int pthread_cond_signal_P ((pthread_cond_t *__cond));
  它用來釋放被阻塞在條件變量cond上的一個線程。多個線程阻塞在此條件變量上時,哪一個線程被喚醒是由線程的調度策略所決定的。要注意的是,必須用保護條件變量的互斥鎖來保護這個函數,否則條件滿足信號又可能在測試條件和調用pthread_cond_wait函數之間被發出,從而造成無限製的等待。
 
6.下麵是使用函數pthread_cond_wait()和函數pthread_cond_signal()的一個簡單的例子。
pthread_mutex_t count_lock;
pthread_cond_t count_nonzero;
unsigned count;
decrement_count () {
pthread_mutex_lock (&count_lock);
while(count==0)
pthread_cond_wait( &count_nonzero, &count_lock);
count=count -1;
pthread_mutex_unlock (&count_lock);
}

increment_count(){
pthread_mutex_lock(&count_lock);
if(count==0)
pthread_cond_signal(&count_nonzero);
count=count+1;
pthread_mutex_unlock(&count_lock);
}
  
count值為0時,decrement函數在pthread_cond_wait處被阻塞,並打開互斥鎖count_lock。此時,當調用到函數increment_count時,pthread_cond_signal()函數改變條件變量,告知decrement_count()停止阻塞。

最後更新:2017-04-02 04:01:46

  上一篇:go 《LINUX設備驅動程序》學習劄記(一)
  下一篇:go 穀“哥”性醜聞還要對穀姐性侵犯?