2)條件變量(cond)
利用線程間共享的全局變量進行同步的一種機制。條件變量上的基本操作有:觸發條件(當條件變為 true 時);等待條件,挂起線程直到其他線程觸發條件。
int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond); //解除所有線程的阻塞
(1)初始化.init()或者pthread_cond_t cond=PTHREAD_COND_INITIALIER(前者為動态初始化,後者為靜态初始化);屬性置為NULL
(2)等待條件成立.pthread_wait,pthread_timewait.wait()釋放鎖,并阻塞等待條件變量為真,timewait()設定等待時間,仍未signal,傳回ETIMEOUT(加鎖保證隻有一個線程wait)
(3)激活條件變量:pthread_cond_signal,pthread_cond_broadcast(激活所有等待線程)
(4)清除條件變量:destroy;無線程等待,否則傳回EBUSY
對于
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
一定要在mutex的鎖定區域内使用。
如果要正确的使用pthread_mutex_lock與pthread_mutex_unlock,請參考
pthread_cleanup_push和pthread_cleanup_pop宏,它能夠線上程被cancel的時候正确的釋放mutex!
另外,posix1标準說,pthread_cond_signal與pthread_cond_broadcast無需考慮調用線程是否是mutex的擁有者,也就是說,可以在lock與unlock以外的區域調用。如果我們對調用行為不關心,那麼請在lock區域之外調用吧。
說明:
(1)pthread_cond_wait 自動解鎖互斥量(如同執行了pthread_unlock_mutex),并等待條件變量觸發。這時線程挂起,不占用CPU時間,直到條件變量被觸發(變量為ture)。在調用 pthread_cond_wait之前,應用程式必須加鎖互斥量。pthread_cond_wait函數傳回前,自動重新對互斥量加鎖(如同執行了pthread_lock_mutex)。
(2)互斥量的解鎖和在條件變量上挂起都是自動進行的。是以,在條件變量被觸發前,如果所有的線程都要對互斥量加鎖,這種機制可保證線上程加鎖互斥量和進入等待條件變量期間,條件變量不被觸發。條件變量要和互斥量相聯結,以避免出現條件競争——個線程預備等待一個條件變量,當它在真正進入等待之前,另一個線程恰好觸發了該條件(條件滿足信号有可能在測試條件和調用pthread_cond_wait函數(block)之間被發出,進而造成無限制的等待)。
(3)pthread_cond_timedwait 和 pthread_cond_wait 一樣,自動解鎖互斥量及等待條件變量,但它還限定了等待時間。如果在abstime指定的時間内cond未觸發,互斥量mutex被重新加鎖,且pthread_cond_timedwait傳回錯誤 ETIMEDOUT。abstime 參數指定一個絕對時間,時間原點與 time 和 gettimeofday 相同:abstime = 0 表示 1970年1月1日00:00:00 GMT。
(4)pthread_cond_destroy 銷毀一個條件變量,釋放它擁有的資源。進入 pthread_cond_destroy 之前,必須沒有在該條件變量上等待的線程。
(5)條件變量函數不是異步信号安全的,不應當在信号處理程式中進行調用。特别要注意,如果在信号處理程式中調用 pthread_cond_signal 或 pthread_cond_boardcast 函數,可能導緻調用線程死鎖。
示例程式1
View Code
示例程式2
3)信号量
如同程序一樣,線程也可以通過信号量來實作通信,雖然是輕量級的。
信号量函數的名字都以"sem_"打頭。線程使用的基本信号量函數有四個。
#include <semaphore.h>
int sem_init (sem_t *sem , int pshared, unsigned int value);
這是對由sem指定的信号量進行初始化,設定好它的共享選項(linux 隻支援為0,即表示它是目前程序的局部信号量),然後給它一個初始值VALUE。
兩個原子操作函數:
int sem_wait(sem_t *sem);
int sem_post(sem_t *sem);
這兩個函數都要用一個由sem_init調用初始化的信号量對象的指針做參數。
sem_post:給信号量的值加1;
sem_wait:給信号量減1;對一個值為0的信号量調用sem_wait,這個函數将會等待直到有其它線程使它不再是0為止。
int sem_destroy(sem_t *sem);
這個函數的作用是再我們用完信号量後都它進行清理。歸還自己占有的一切資源。
參考:
【3】 線程函數介紹
<a href="http://www.unix.org/version2/whatsnew/threadsref.html">http://www.unix.org/version2/whatsnew/threadsref.html</a>
【5】 線程常用函數簡介
<a href="http://www.rosoo.net/a/201004/8954.html">http://www.rosoo.net/a/201004/8954.html</a>
【6】 條件變量
<a href="http://blog.csdn.net/hiflower/article/details/2195350">http://blog.csdn.net/hiflower/article/details/2195350</a>
【7】條件變量函數說明
<a href="http://blog.csdn.net/hairetz/article/details/4535920">http://blog.csdn.net/hairetz/article/details/4535920</a>