淺析linux下的條件變量

??一.條件變量

? ? 條件變量是用來等待線程而不是上鎖的,條件變量通常和互斥鎖一起使用。條件變量之所以要和互斥鎖一起使用,主要是因為互斥鎖的一個明顯的特點就是它只有兩種狀態:鎖定和非鎖定,而條件變量可以通過允許線程阻塞和等待另一個線程發送信號來彌補互斥鎖的不足,所以互斥鎖和條件變量通常一起使用

? ? 當條件滿足的時候,線程通常解鎖并等待該條件發生變化,一旦另一個線程修改了環境變量,就會通知相應的環境變量喚醒一個或者多個被這個條件變量阻塞的線程。這些被喚醒的線程將重新上鎖,并測試條件是否滿足。一般來說條件變量被用于線程間的同步;當條件不滿足的時候,允許其中的一個執行流掛起和等待。

條件變量中常用的API:

? ? ?1).條件變量類型為:pthread_cond_t ,類似互斥變量,條件變量的初始化有兩種方式:

? ? ? 靜態:pthread_cond_t mycon=PTHREAD_COND_INITIALIZER;

? ? ? 動態:通過調用pthread_cond_init函數,函數原型為:

[cpp]?view plain?copy
  1. 靜態:pthread_cond_t?mycon=PTHREAD_COND_INITIALIZER;??

? ? ?cond:環境變量.

? ? ?attr:條件變量屬性.

? ? ?成功返回0,失敗返回錯誤碼.

? ? ?2).條件變量摧毀函數:pthread_cond_destroy(&mycond);

[cpp]?view plain?copy
  1. int?pthread_cond_destroy(pthread_cond_t?*cond);??

? ? ?成功返回0,失敗返回錯誤碼.

? ? ?摧毀所指定的條件變量,同時將會釋放所給它分配的資源。調用該函數的進程也并不等待在參數所指定的條件變量上。

? ? ?3).條件變量等待函數。pthread_cond_wait(&mycond,&mylock);

? ? ?

[cpp]?view plain?copy
  1. int?pthread_cond_timedwait(pthread_cond_t?*restrict?cond,??
  2. ???????????pthread_mutex_t?*restrict?mutex,??
  3. ???????????const?struct?timespec?*restrict?abstime);??
  4. ????int?pthread_cond_wait(pthread_cond_t?*restrict?cond,??
  5. ???????????pthread_mutex_t?*restrict?mutex);??

? ? cond:條件變量

? ? mutex:互斥鎖

?pthread_cond_wait和pthread_cond_timedwait的區別:

? ??pthread_cond_timedwait函數類型與函數pthread_cond_wait,區別在于,如果達到或是超過所引用的參數*abstime,它將結束并返回錯誤ETIME.

? ? timespec

[cpp]?view plain?copy
  1. typedef?struct?timespec??
  2. ???{??
  3. ??????time_t?????tv_sec;????//!>?秒??
  4. ??????long?????tv_nsex;????//!>?毫秒??
  5. ???}timespec_t;??

? ? 當時間超過之前預設定的時會返回錯誤.

? ? 4).條件變量通知函數:pthread_cond_signal和pthread_cond_broadcast

[cpp]?view plain?copy
  1. int?pthread_cond_broadcast(pthread_cond_t?*cond);??
  2. int?pthread_cond_signal(pthread_cond_t?*cond);??

pthread_cond_signal和pthread_cond_broadcast的區別:

? ? ? ?pthread_cond_signal:只喚醒一個在相同條件變量中阻塞的線程將會被喚醒

? ? ? ?pthread_cond_broadcast:喚醒等待隊列中的所有線程

二.一個關于互斥鎖和條件變量的栗子

? ?栗子:用互斥鎖和條件變量的概念實現一個簡單的生產者和消費者的模型。

?生產者和消費者模型:

? ? 1).滿足互斥與同步條件,用互斥鎖和條件變量實現

? ? 2).多個生產者和消費者:生產者和生產者屬于互斥關系;生產者和消費者屬于互斥和同步關系;消費者和消費者屬于競爭關系,需要互斥鎖

? ? 3).生產者和消費者模型中存在如下幾種關系和角色:3種關系,2種角色,1種交換媒介(一般是一段內存)

? ? 下例以單生產者和單消費者,交換媒介為鏈表實現的生產者消費者模型

? ? ?

[cpp]?view plain?copy
  1. procon.c??
  2. ??
  3. #include<stdio.h>??
  4. #include<stdlib.h>??
  5. #include<assert.h>??
  6. #include<pthread.h>??
  7. ??
  8. typedef?struct?LinkNode??
  9. {??
  10. ????int?data;??
  11. ????struct?LinkNode?*next;??
  12. }Node;??
  13. ??
  14. pthread_mutex_t?mylock=PTHREAD_MUTEX_INITIALIZER;??
  15. pthread_cond_t?mycond=PTHREAD_COND_INITIALIZER;??
  16. ??
  17. Node?*CreatNode(int?data)??
  18. {??
  19. ????Node?*NewNode=(Node?*)malloc(sizeof(Node));??
  20. ????if(NULL?==?NewNode)??
  21. ????{??
  22. ????????perror("malloc");??
  23. ????????return?NULL;??
  24. ????}??
  25. ????NewNode->data=data;??
  26. ????NewNode->next=NULL;??
  27. ????return?NewNode;??
  28. }??
  29. ??
  30. void?InitLink(Node?**head)??
  31. {??
  32. ????*head=CreatNode(0);??
  33. }??
  34. ??
  35. int?IsEmpty(Node?*head)??
  36. {??
  37. ????assert(head);??
  38. ????if(head->next)??
  39. ????????return?0;????//not?empty??
  40. ????else??
  41. ????????return?1;????//empty??
  42. }??
  43. ??
  44. void?PushFront(Node?*head,int?data)??
  45. {??
  46. ????assert(head);??
  47. ????Node?*NewNode=CreatNode(data);??
  48. ????NewNode->next=head->next;??
  49. ????head->next=NewNode;??
  50. }??
  51. ??
  52. void?PopFront(Node?*head,int?*data)??
  53. {??
  54. ????assert(data);??
  55. ????assert(head);??
  56. ????if(IsEmpty(head))??
  57. ????{??
  58. ????????printf("empty?link\n");??
  59. ????????return?;??
  60. ????}??
  61. ????Node?*del=head->next;??
  62. ????*data=del->data;??
  63. ????head->next=del->next;??
  64. ????free(del);??
  65. ????del=NULL;??
  66. }??
  67. ??
  68. void?DisplayLink(Node?*head)??
  69. {??
  70. ????assert(head);??
  71. ????Node?*cur=head->next;??
  72. ????while(cur)??
  73. ????{??
  74. ????????printf("%d?",cur->data);??
  75. ????????cur=cur->next;??
  76. ????}??
  77. ????printf("\n");??
  78. }??
  79. ??
  80. void?DestroyLink(Node?*head)??
  81. {??
  82. ????int?data=0;??
  83. ????assert(head);??
  84. ????while(!IsEmpty(head))??
  85. ????{??
  86. ????????PopFront(head,&data);??
  87. ????}??
  88. ????free(head);??
  89. }??
  90. ??
  91. void?*product_run(void?*arg)??
  92. {??
  93. ????int?data=0;??
  94. ????Node?*head=(Node?*)arg;??
  95. ????while(1)??
  96. ????{??
  97. ????????usleep(100000);??
  98. ????????data=rand()%1000;??
  99. ????????pthread_mutex_lock(&mylock);??
  100. ????????PushFront(head,data);??
  101. ????????pthread_mutex_unlock(&mylock);??
  102. ????????pthread_cond_signal(&mycond);??
  103. ????????printf("product?is?done,data=%d\n",data);??
  104. ????}??
  105. }??
  106. ??
  107. void?*consumer_run(void?*arg)??
  108. {??
  109. ????int?data=0;??
  110. ????Node?*head=(Node?*)arg;??
  111. ????while(1)??
  112. ????{??
  113. ????????pthread_mutex_lock(&mylock);??
  114. ????????while(IsEmpty(head))??
  115. ????????{??
  116. ????????????pthread_cond_wait(&mycond,&mylock);??
  117. ????????}??
  118. ????????PopFront(head,&data);??
  119. ????????pthread_mutex_unlock(&mylock);??
  120. ????????printf("consumer?is?done,data=%d\n",data);??
  121. ????}??
  122. }??
  123. ??
  124. void?testprocon()??
  125. {??
  126. ????Node?*head=NULL;??
  127. ????InitLink(&head);??
  128. ????pthread_t?tid1;??
  129. ????pthread_t?tid2;??
  130. ????pthread_create(&tid1,NULL,product_run,(void?*)head);??
  131. ????pthread_create(&tid2,NULL,consumer_run,(void?*)head);??
  132. ??
  133. ????pthread_join(tid1,NULL);??
  134. ????pthread_join(tid2,NULL);??
  135. ????DestroyLink(head);??
  136. ????pthread_mutex_destroy(&mylock);??
  137. ????pthread_cond_destroy(&mycond);??
  138. ??
  139. }??
  140. int?main()??
  141. {??
  142. ????testprocon();??
  143. ????return?0;??
  144. }??
  145. ??
  146. Makefile??
  147. procon:procon.c??
  148. ????gcc?-o?$@?$^?-lpthread??
  149. .PHONY:clean??
  150. clean:??
  151. ????rm?-f?procon??


? ??

總結:

? ?條件變量用在某個線程需要在某種條件才去保護它將要操作的臨界區的情況下,從而避免了線程不斷輪詢檢查該條件是否成立而降低效率的情況,這是實現了效率提高。

? 希望對讀者有幫助吧~~~~

? ??

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384000.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384000.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384000.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

UVa1587

【題目描述】 傳送門 【題目分析】 剛開始想簡單了&#xff0c;認為只要相對的面相等就可以了。然后發現三個不同方向的面的邊應該有相等的關系&#xff0c;即如果兩個面公用一條邊&#xff0c;那么這兩個面的另外兩條邊就是另一個面的兩條邊。而且這三個量里面肯定有一個最…

Linux多線程與同步

https://www.cnblogs.com/freedomabcd/p/7774743.html 典型的UNIX系統都支持一個進程創建多個線程(thread)。在Linux進程基礎中提到&#xff0c;Linux以進程為單位組織操作&#xff0c;Linux中的線程也都基于進程。盡管實現方式有異于其它的UNIX系統&#xff0c;但Linux的多線程…

內存管理(二)

頁面置換算法 當發生缺頁中斷的時候, 系統會在內存中選擇一個頁面將其換出內存, 而當換出內存的時候如果該頁面的內容在內存中發生修改,則必須將該新數據重新寫回到磁盤, 然后再將需要換進的數據覆蓋掉原來的數據, 而當該數據在內存中沒有被修改的時候, 此時就直接用需要換進的…

兩個棧實現一個隊列/兩個隊列實現一個棧

http://blog.csdn.net/sinat_30472685/article/details/70157227 1兩個棧實現一個隊列 1.原理分析&#xff1a; 隊列的主要操作有兩個&#xff1a;入隊操作和出隊操作&#xff0c;出隊時從隊頭出&#xff0c;入隊是從隊尾插入&#xff0c;入隊的操作和入棧的操作類似&#xff0…

UVa1588

【題目描述】 傳送門 【題目分析】 剛開始想了一會沒有想到什么很好的算法&#xff0c;看到了長度最多為100&#xff0c;就知道自己想的沒有什么意義了&#xff0c;直接暴力&#xff0c;把每一種填法都試一下就知道了。適當剪枝一下&#xff08;一個簡單的樂觀函數&#xff…

轉:C++中const、volatile、mutable的用法

const修飾普通變量和指針 const修飾變量&#xff0c;一般有兩種寫法&#xff1a; const TYPE value; TYPE const value; 這兩種寫法在本質上是一樣的。它的含義是&#xff1a;const修飾的類型為TYPE的變量value是不可變的。對于一個非指針的類型TYPE&#xff0c;無論怎么寫&…

數據鏈路

廣播信道的數據鏈路層 局域網的優點 網絡為一個單位所擁有, 地理范圍和站點數有限 局域網具有廣播特性, 可以從一個站點方便地訪問到整個網絡. 各個主機之間可以共享資源, 無論是局域網上的硬件資源還是局域網上的軟件資源 便于系統的擴展換和演化, 各個設備之間的位置可靈…

UVa11809

【題目描述】 傳送門 【題目分析】 終于把這道題做完了&#xff0c;之前一直連題意都看不懂。實在不行上網找了一下大佬的博客&#xff0c;看懂題意后自己寫&#xff0c;發現讀入很難處理&#xff0c;就又學習了一下大佬的讀入方法&#xff0c;用的是C里面的sstream&#xf…

數據鏈路層:基本概念

數據鏈路層的定義 對數據鏈路層有對上的網絡層接口. 對下提供物理層的接口. 定義合適的傳輸差錯率 對傳輸流進行管理, 以免快速的傳輸的數據被淹沒. 比如發送端發送信號太快, 接受方接受速度較慢, 此時數據鏈路層就需要提供一定的功能解決這個問題 物理層上傳輸的基本單元是…

C++的沉迷與愛戀

每年的 09/28 於我都是一個特殊的日子 -- 不只是因為教師節。今年很特殊地沒有普天同慶&#xff0c;那麼我就寫篇文章自己慶祝一下好了。我於今年七月發表了一本著作《多型與虛擬》和一本譯作《深度探索C物件模型》&#xff0c;獲得很大的回響。這些作品都不是針對 C 的完全初學…

Insertion Sort——打表找規律

【題目描述】 Insertion sort is a simple sorting algorithm that builds the final sorted array one item at an iteration.More precisely, insertion sort iterates, consuming one input element each repetition, and growing a sorted output list. At each iteration…

數據鏈路層: 可靠性傳輸 六個協議

可靠性傳輸 1. 差錯控制 發送方將數據幀發送, 但是當發送方發送的是一個 1的時候此時接受方卻接受的是一個 0. (1)校驗 接收方如果幀校驗接受到的幀沒有問題, 則對發送方發送一個肯定性的確認, 當對這個數據幀進行校驗發現這個幀有問題的時候, 此時接受方一種是將這個數據幀…

c語言實現配置文件的讀寫

配置文件的格式如下&#xff1a; key1 value1 key2 value2 . . . 名值對以一個鏈接&#xff0c;一條記錄以換行符分割 頭文件&#xff1a; #include<stdio.h> #include<stdlib.h> #include <string.h> 函數原型&#xff1a; void trim(char *strIn, char *…

Educational Codeforces Round 73 (Rated for Div. 2)

A 很簡單的一個模擬&#xff0c;只要前面的數字有兩個以上就能合成后面的&#xff0c;我們進行一遍合成看能不能出現2048就可以了。 #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include&…

數據鏈路層: HDLC

一. 協議機 發送方和接收方. 同時有限狀態機把協議形式化為一個四元組 (S,M,I,T), 其中你S表示進程和信道可能進入的集合, M 表示數據幀的狀態, I 表示進程的初始狀態, T 表示兩兩狀態之間的轉化. 每個系統狀態可以分為發送狀態, 接受狀態和信道狀態. 把狀態用一個點進行表示,…

Miller_Rabin算法

為了測試一個大整數是不是素數&#xff0c;我們不能夠使用傳統的測試是否有因子的方法&#xff0c;因為那樣的時間復雜度至少也是O(n)O(n)O(n)&#xff0c;空間復雜度是O(n)O(n)O(n)&#xff08;使用線性篩數法&#xff09;&#xff0c;時間復雜度還好說&#xff0c;空間復雜度…

bob-tong 字符串函數之Strtok()函數

https://www.cnblogs.com/Bob-tong/p/6610806.html Strtok()函數詳解&#xff1a; 該函數包含在"string.h"頭文件中 函數原型&#xff1a; char* strtok (char* str,constchar* delimiters ); 函數功能&#xff1a; ??切割字符串&#xff0c;將str切分成一個個子…

數據鏈路層:SLIP(串型線路IP) PPP(點對點協議)

SLIP 沒有差錯控制, 傳輸時必須知道對方IP, 傳輸使用于低速業務 19.2k.應用非常受限 PPP協議 1. PPP協議功能 處理錯誤檢測 支持多協議(IP, IPX, DECnet 等) 連接時允許協商 IP 地址 允許身份驗證 2. PPP 的組成 串型鏈路上封裝數據報, 即支持異步鏈路也支持面向 比特…

Honeycomb——BFS

【題目描述】 傳送門 【題目分析】 看起來很復雜好像還要建圖什么的&#xff0c;其實直接在原圖上BFS就可以了&#xff0c;設置一下方向數組&#xff0c;然后直接跑就可以了。 【AC代碼】 #include<cstdio> #include<cstring> #include<algorithm> #inc…

C語言中strspn()函數和strcspn()函數的對比使用

C語言strspn()函數&#xff1a;計算字符串str中連續有幾個字符都屬于字符串accept 頭文件&#xff1a;#include <string.h> strspn() 函數用來計算字符串 str 中連續有幾個字符都屬于字符串 accept&#xff0c;其原型為&#xff1a; size_t strspn(const char *str, con…