這篇文章只講述下條件變數pthread_cond_t的作用和理解,函數已在別的文章中給出。
互斥鎖一個明顯的缺點是它只有兩種狀態:鎖定和非鎖定。而條件變數通過允許線程阻塞和等待另一個線程發送訊號的方法彌補了互斥鎖的不足,它常和互斥鎖一起使用。
(1)等待機制
使用時,條件變數被用來阻塞一個線程:
當條件不滿足時,線程往往解開相應的互斥鎖並等待條件發生變化;
一旦其它的某個線程改變了條件變數,系統將通知相應的條件變數喚醒一個或多個正被此條件變數阻塞的線程。這些線程將重新鎖定互斥鎖並重新測試條件(檢測條件必須是全域變數,所有需要同步的線程能夠訪問)是否滿足。
個人比較喜歡用布爾型變數來做測試條件,如:bool bIsLocked=false;
(2)條件變數只是起阻塞和喚醒線程的作用,具體的判斷條件還需使用者給出,例如一個變數是否為真等等。
線程被喚醒後,它將重新檢查判斷條件是否滿足,如果還不滿足,一般說來線程應該仍阻塞在這裡,被等待被下一次喚醒。這個過程一般用while語句實現。
while(bLock==true) pthread_cond_wait(&g_cond, &g_mutex);
注意:如果判斷條件陳述式用if(),則線程會在被喚醒後,直接鎖定以執行後面的程式(不再等待條件變數),如果有其他的線程也在等待相同的變數並被喚醒,則這兩個線程會同時去擷取互斥鎖,從而導致死結的發生。
(3)多個線程阻塞在此條件變數上時,哪一個線程被喚醒是由線程的調度策略所決定的。
(4)必須用保護條件變數的互斥鎖來保護喚醒函數pthread_cond_signal(),否則條件滿足時,訊號又可能在測試條件和調用pthread_cond_wait函數之間被發出,從而造成無限制的等待。
即pthread_cond_signal()需要放在pthread_mutex_lock()和pthread_mutex_unlock()之間。
(5)條件變數的等待和喚醒是一對一的關係,有點類似於開關。
(6)pthread_cond_wait()函數的說明:該函數在條件滿足之後,立刻返回,然後去擷取互斥鎖,以執行接下來的操作。
注意:pthread_cond_wait()函數條件滿足之後重新擷取互斥鎖的過程比較慢,所以必須用while(判斷條件)判斷,在此期間是否有別的線程已經使得條件不滿足。
下面是自己寫的一個例子:
全域變數:
//互池鎖pthread_mutex_t g_mutex;//條件變數pthread_cond_t g_cond;//標識變數bool bLock;unsigned int count;
線程的回呼函數:
void * increment_count(void * arg){ pthread_mutex_lock(&g_mutex); while(bLock) pthread_cond_wait(&g_cond, &g_mutex); bLock=1; count+=1; printf("increment thread: count+=1\n"); pthread_cond_signal(&g_cond); pthread_mutex_unlock(&g_mutex); bLock=0;}