1、條件變量的概念
一個線程A的執行需要另一個線程B來喚醒,否則A掛起等待。線程B可以產生線程A繼續執行的信號。條件變量常用在共享數據狀態變化的場景中,例如:生產則和消費者問題。POSIX線程庫提供了條件變量這種同步機制。使用條件變量需要聯合互斥鎖一起使用。
2、如何聲明一個條件變量
#include <pthread.h>
pthread_cond_t cond;
3、如何初始化一個條件變量
//靜態初始化條件變量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
//動態初始化條件變量
pthread_cond_t cond;
pthread_cond_init(&cond,NULL);
//結合互斥鎖的條件變量初始化結構變量
typedef struct{
pthread_mutex_t mutex;//互斥
pthread_cond_t cond;//條件
int value;//變量資源
}mutexcond_t;
mutexcond_t mymutexcond = {PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER,0};
靜態初始化的條件變量不需要銷燬,動態初始化的條件變量需要銷燬,銷燬函數聲明如下:
int pthread_cond_destroy(pthread_cond_t *cond);
4、如何阻塞含條件變量的線程
線程執行等待條件變量後,將一直阻塞或計時阻塞,兩個函數接口:pthread_cond_wait,pthread_cond_timewait。
int pthread_cond_wait(pthread_cond_t * restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_timewait(pthread_cond_t * restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);
關鍵字:restrict,限制,表明指針修飾的指針是訪問一個數據對象的惟一且初始的方式。
pthread_cond_wait傳入兩個參數,一個條件變量cond指針和一個互斥變量mutex指針。互斥變量的作用是防止多線程同時調用pthread_cond_wait形成競爭。
5、如何喚醒等待條件變量的線程
//只喚醒一個等待條件變量的線程
int pthread_cond_signal(pthread_cond_t *cond);
//喚醒所有等待條件變量的線程
int pthread_cond_broadcast(pthread_cond_t *cond);
6、總結用法
條件變量和互斥鎖的用法比較繞,總結一下就是。
- 調用pthread_cond_wait之前,必須給互斥鎖上鎖pthread_mutex_lock(&mutex)。
- 一旦執行到pthread_cond_wait,如果沒有收到pthead_cond_signal發出的cond信號,pthread_cond_wait會自動解鎖,並一直阻塞。
- 一旦pthread_cond_wait收到pthread_cond_signal發出的cond信號,pthread_cond_wait會自動加鎖,因此,條件變量滿足後進入臨界區,執行結束需要pthread_mutex_unlock(&mutex)解鎖。
// 線程1
{
pthread_mutex_lock(&mutex);
...
pthread_cond_signal(&cond);//喚醒等待cond的線程
...
pthread_mutex_unlock(&mutex);
}
// 線程2
{
pthread_mutex_lock(&mutex);
...
pthread_cond_wait(&cond,&mutex);//等待條件變量
...
pthread_mutex_unlock(&mutex);
}