Linux编程练习 --多线程4--条件变量
上一篇練習了互斥鎖的用法和原理,這次學習和互斥鎖一起應用的cond--條件變量
1.互斥鎖的存在問題:
互斥鎖一個明顯的缺點是它只有兩種狀態:鎖定和非鎖定。設想一種簡單情景:多個線程訪問同一個共享資源時,并不知道何時應該使用共享資源,如果在臨界區里加入判斷語句,或者可以有效,但一來效率不高,二來復雜環境下就難以編寫了,這是我們需要一個結構,能在條件成立時觸發相應線程,進行變量修改和訪問。
2.條件變量:
條件變量通過允許線程阻塞和等待另一個線程發送信號的方法彌補了互斥鎖的不足,它常和互斥鎖一起使用。使用時,條件變量被用來阻塞一個線程,當條件不滿足時,線程往往解開相應的互斥鎖并等待條件發生變化。一旦其它的某個線程改變了條件變量,它將通知相應的條件變量喚醒一個或多個正被此條件變量阻塞的線程。這些線程將重新鎖定互斥鎖并重新測試條件是否滿足。
3.條件變量的相關函數
頭文件:#include <pthread.h>
?????? pthread_cond_t cond = PTHREAD_COND_INITIALIZER;?//條件變量結構
?????? int??? pthread_cond_init(pthread_cond_t??? *cond,& ;nbsp;?? pthread_condattr_t
?????? *cond_attr);
?????? int pthread_cond_signal(pthread_cond_t *cond);
?????? int pthread_cond_broadcast(pthread_cond_t *cond);
?????? 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);
?????? int pthread_cond_destroy(pthread_cond_t *cond);
詳細說明:
??(1)創建和注銷
條件變量和互斥鎖一樣,都有靜態動態兩種創建方式
?a.靜態方式
靜態方式使用PTHREAD_COND_INITIALIZER常量,如下:
pthread_cond_t cond=PTHREAD_COND_INITIALIZER
?b.動態方式
動態方式調用pthread_cond_init()函數,API定義如下:
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr)
盡管POSIX標準中為條件變量定義了屬性,但在LinuxThreads中沒有實現,因此cond_attr值通常為NULL,且被忽略。
注銷一個條件變量需要調用pthread_cond_destroy(),只有在沒有線程在該條件變量上等待的時候才能注銷這個條件變量,否則返回EBUSY。因為Linux實現的條件變量沒有分配什么資源,所以注銷動作只包括檢查是否有等待線程。API定義如下:
int pthread_cond_destroy(pthread_cond_t *cond)
(2)等待和激發
a.等待
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)//有時等待
等待條件有兩種方式:無條件等待pthread_cond_wait()和計時等待pthread_cond_timedwait(),其中計時等待方式如果在給定時刻前條件沒有滿足,則返回ETIMEOUT,結束等待,其中abstime以與time()系統調用相同意義的絕對時間形式出現,0表示格林尼治時間1970年1月1日0時0分0秒。
無論哪種等待方式,都必須和一個互斥鎖配合,以防止多個線程同時請求pthread_cond_wait()(或 pthread_cond_timedwait(),下同)的競爭條件(Race Condition)。mutex互斥鎖必須是普通鎖(PTHREAD_MUTEX_TIMED_NP)或者適應鎖(PTHREAD_MUTEX_ADAPTIVE_NP),且在調用pthread_cond_wait()前必須由本線程加鎖(pthread_mutex_lock()),而在更新條件等待隊列以前,mutex保持鎖定狀態,并在線程掛起進入等待前解鎖。在條件滿足從而離開 pthread_cond_wait()之前,mutex將被重新加鎖,以與進入pthread_cond_wait()前的加鎖動作對應。
?
b.激發
激發條件有兩種形式,pthread_cond_signal()激活一個等待該條件的線程,存在多個等待線程時按入隊順序激活其中一個;而pthread_cond_broadcast()則激活所有等待線程。
?
(3). 其他操作
pthread_cond_wait ()和pthread_cond_timedwait()都被實現為取消點,因此,在該處等待的線程將立即重新運行,在重新鎖定mutex后離開 pthread_cond_wait(),然后執行取消動作。也就是說如果pthread_cond_wait()被取消,mutex是保持鎖定狀態的,因而需要定義退出回調函數來為其解鎖。
?
看完基本操作后做一個小練習:
建立兩個線程1、2,兩個線程分別訪問共享資源,并進行加 1操作,當共享資源<=3時,線程1掛起不操作,這時線程2工作,共享資源>3后,兩者都工作
[cpp]?view plaincopy
?
編譯,運行,可以看到預期結果,這里只是一個簡單練習,例子不怎么好,以后再深入研究條件變量,用條件變量解決生產者--消費者問題
總結
以上是生活随笔為你收集整理的Linux编程练习 --多线程4--条件变量的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 美国最大水库因干涸发现多具藏尸:加州许多
- 下一篇: 5分钟看完苹果WWDC2022大会:iO