日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux编程练习 --多线程4--条件变量

發布時間:2023/12/10 linux 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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
  • /*condmutex.c*/??
  • #include?<stdlib.h>????
  • #include?<stdio.h>????
  • #include?<pthread.h>????
  • #include?<errno.h>?????
  • /*全局變量*/??
  • int?gnum?=?0;??
  • /*互斥量?*/??
  • pthread_mutex_t?mutex;??
  • /*條件變量*/??
  • pthread_cond_t??cond;??
  • /*聲明線程運行服務程序*/??
  • static?void?pthread_func_1?(void);?????
  • static?void?pthread_func_2?(void);?????
  • int?main?(void)?????
  • {?????
  • ????/*線程的標識符*/??
  • ????pthread_t?pt_1?=?0;?????
  • ????pthread_t?pt_2?=?0;?????
  • ????int?ret?=?0;?????
  • ??????
  • ????/*互斥初始化*/??
  • ????pthread_mutex_init?(&mutex,?NULL);???
  • ????/*條件變量初始化*/??
  • ????pthread_cond_init(&cond,NULL);??
  • ????/*分別創建線程1、2*/??
  • ????ret?=?pthread_create?(&pt_1,????????????//線程標識符指針??
  • ????????NULL,???????????//默認屬性??
  • ????????(void?*)pthread_func_1,//運行函數??
  • ????????NULL);??????????//無參數??
  • ????if?(ret?!=?0)?????
  • ????{?????
  • ????????perror?("pthread_1_create");?????
  • ????}?????
  • ??????
  • ????ret?=?pthread_create?(&pt_2,????????????//線程標識符指針??
  • ????????NULL,???????????//默認屬性????
  • ????????(void?*)pthread_func_2,?//運行函數??
  • ????????NULL);??????????//無參數??
  • ????if?(ret?!=?0)?????
  • ????{?????
  • ????????perror?("pthread_2_create");?????
  • ????}?????
  • ????/*等待線程1、2的結束*/??
  • ????pthread_join?(pt_1,?NULL);?????
  • ????pthread_join?(pt_2,?NULL);?????
  • ??????
  • ????printf?("main?programme?exit!/n");????
  • ????return?0;?????
  • }?????
  • /*線程1的服務程序*/??
  • static?void?pthread_func_1?(void)?????
  • {?????
  • ????int?i?=?0;?????
  • ??????
  • ????for?(;;)?????
  • ????{?????
  • ????????printf?("This?is?pthread1!/n");??????
  • ????????pthread_mutex_lock(&mutex);?/*獲取互斥鎖*/??
  • ????????/*注意,這里以防線程的搶占,以造成一個線程在另一個線程sleep時多次訪問互斥資源,所以sleep要在得到互?
  • 斥鎖后調用*/??
  • ????????sleep?(1);??
  • ????????/*條件變量,當gnum<=3時,線程1自己掛起并且解鎖,讓線程2進去*/??
  • ????????while?(gnum?<=?3)?{??
  • ????????????pthread_cond_wait(&cond,?&mutex);??
  • ????????}??
  • ????????/*當線程2調用pthread_cond_signal(&cond)時,線程1在這里重啟*/??
  • ????????/*臨界資源*/??
  • ????????gnum++;??
  • ????????printf?("Thread1?add?one?to?num:%d/n",gnum);??
  • ????????pthread_mutex_unlock(&mutex);?/*釋放互斥鎖*/??
  • ??????????
  • ??????????
  • ??????????
  • ????}?????
  • }?????
  • /*線程2的服務程序*/???
  • static?void?pthread_func_2?(void)?????
  • {?????
  • ????int?i?=?0;?????
  • ??????
  • ????for?(;;)?????
  • ????{?????
  • ????????printf?("This?is?pthread2!/n");???
  • ????????pthread_mutex_lock(&mutex);?/*獲取互斥鎖*/??
  • ????????/*注意,這里以防線程的搶占,以造成一個線程在另一個線程sleep時多次訪問互斥資源,所以sleep要在得到互?
  • 斥鎖后調用*/??
  • ????????sleep?(1);??
  • ????????/*臨界資源*/??
  • ????????gnum++;??
  • ????????printf?("Thread2?add?one?to?num:%d/n",gnum);??
  • ????????/*當gnum?==?4時,觸發*/??
  • ????????if?(gnum?==?4)???
  • ????????????pthread_cond_signal(&cond);??
  • ??????????
  • ????????pthread_mutex_unlock(&mutex);?/*釋放互斥鎖*/??
  • ??????????
  • ????}?????
  • ??????
  • ????pthread_exit?(0);?????
  • }????
  • ?

    編譯,運行,可以看到預期結果,這里只是一個簡單練習,例子不怎么好,以后再深入研究條件變量,用條件變量解決生產者--消費者問題

    總結

    以上是生活随笔為你收集整理的Linux编程练习 --多线程4--条件变量的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。