(1) 什么是條件變量實現線程同步?
假如我們的程序中有兩個線程,一個是生產者線程,另一個是消費者線程,生產者線程每隔一段時間把數據寫入到緩沖區buffer中,而消費者線程則每隔一段時間從buffer中取出數據,為了避免兩個線程讀寫混亂,我們讓生產線線程寫完后再通知消費者來讀數據,那么則可以用條件變量來實現線程的同步。
(2) 條件變量的兩個動作
條件不滿足: 阻塞線程
條件滿足: 通知阻塞的線程開始工作
(3) 條件變量的類型:
pthread_cond_t cond;
(4) 主要函數:
初始化一個條件變量(?第二參數一般為NULL)
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
銷毀一個條件變量
int pthread_cond_destroy(pthread_cond_t *cond);
阻塞等待一個條件變量
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
? ? ? ?阻塞線程
? ? ? ?將已經上鎖的mutex解鎖
? ? ? ?解除阻塞后會對mutex加鎖
限時等待一個條件變量
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
激活一個等待該條件的線程,存在多個等待線程時按入隊順序激活其中一個。
int pthread_cond_signal(pthread_cond_t *cond);
喚醒全部阻塞在條件變量上的線程
int pthread_cond_broadcast(pthread_cond_t *cond);
?
(5)注意事項
注意 1:
mutex 互斥鎖必須是普通鎖(PTHREAD_MUTEX_TIMED_NP)或者適應鎖(PTHREAD_MUTEX_ADAPTIVE_NP)。
在調用 pthread_cond_wait()前必須由本線程加鎖 pthread_mutex_lock()。
在更新條件等待隊列以前,mutex 保持鎖定狀態。
在線程掛起進入等待前解鎖。
注意 2:
在條件滿足從而離開 pthread_cond_wait() 之前,mutex 將被重新加鎖,以與進入
pthread_cond_wait()前的加鎖動作對應。
也就是說在做 pthread_cond_wait 之前,往往要用 pthread_mutex_lock 進行加鎖,而
調 pthread_cond_wait 函 數 會 將 鎖 解 開 , 然 后 將 線 程 掛 起 阻 塞 。 直 到 條 件 被
pthread_cond_signal 激發,該函數內部又會將鎖狀態恢復為鎖定狀態,最后再用
pthread_mutex_unlock 進行解鎖。
注意 3:
pthread_cond_wait() 和 pthread_cond_timedwait()都被實現為取消點,也就是說如果
pthread_cond_wait()被取消,則退出阻塞,然后將鎖狀態恢復,然后當前線程就會終止。即
互斥鎖又恢復鎖定狀態,然而當前線程已經被取消掉,那么這個互斥鎖就不會被解開了,此
時鎖得不到釋放,就會造成死鎖,因而需要在線程退出前為其解鎖。
?
(5)示例
1.初始化條件變量和互斥鎖pthread_mutex_init(&mutex, NULL);pthread_cond_init(&cond, NULL);2.在線程中使用
(1)生產者線程pthread_mutex_lock(&mutex);// 使用互斥鎖保護共享數據對緩沖區buffer寫入操作pthread_cond_signal(&cond);// 通知阻塞的消費者線程,數據寫入完畢,可以解除阻塞了pthread_mutex_unlock(&mutex);(2)消費者線程pthread_mutex_lock(&mutex); //調用pthread_cond_wait前一般都會搭配pthread_mutex_lockpthread_cond_wait(&cond, &mutex); //等待生產者線程的通知從緩沖區buffer中讀出數據pthread_mutex_unlock(&mutex); //解鎖3.銷毀條件變量和互斥鎖pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);
?
本文參考文章:
https://www.cnblogs.com/hesper/p/10738996.html
https://www.cnblogs.com/harlanc/p/8596211.html
?