基於鍊錶和環形佇列的生產者消費者模型

2021-08-18 18:02:06 字數 3357 閱讀 2960

在學習系統程式設計當中,有一種很重要的模型,那就是生產者消費者模型,在編寫多執行緒**時候,乙個個執行緒就扮演著生產者,消費者的角色。舉乙個例子,在生活中,我們去商店買東西,那麼我們相當於消費者,而貨物生成廠家就是生產者,商店扮演著交易場所。我們總結為:

生產者和生產者

這些廠商在生產貨物的時候,加入都生產一種貨物,而一家商店只需要從一家廠商訂購貨物,那麼這些廠商之間就會競爭這個名額,故而生產者生產者之間存在一種互斥的關係。

生產者消費者

商家的商品再生產完成之間,我們是不能夠購買的,所以存在互斥關係,並且當貨架上面的貨物滿的時候,廠家是不會去送貨物的,只有等待消費者消費了貨物之後,才會生產,而且,當貨物被買完的時候,消費者必須要等廠商供貨來,才可以消費,因此,生產者和消費者存在同步關係。

消費者和消費者

當貨物的資源有限的時候,而需求量又很大,那麼消費者之間就會競爭這個資源,就會存在互斥關係。

我們再把上面的例子例項到我們的作業系統中時,當我們編寫幾個執行緒同時往一快記憶體中寫資料,另外幾個執行緒就是從這塊記憶體中讀取資料,那麼就是典型的生產者,消費者模型,幾個寫執行緒之間必須要互斥的訪問這塊記憶體,同樣的,讀執行緒也必須互斥的訪問,讀寫執行緒互斥而且同步,如果無法保證這些條件,那麼就會造成執行緒訪問臨界資源的錯誤。下面我們來基於鍊錶實現乙個生產者,消費者模型,

1

#include

2#include

3#include

4#include

5 typedef struct node

6 node,*pnode,**ppnode;

10void allocnode(ppnode pphead)

11 18 (*pphead)->next=

null;

19return ;

20 }

21void pushfront(pnode head,int x)

22

29 p->next=

null;

30 p->

data

=x; 31 p->next=head->next;

32 head->next=p;

3334

35 }

36void popfront(pnode head,int* x)

37

47 int isempty(pnode head)

48

51void show(pnode head)

52 60 printf("\n");

61 }

62void destroylist(pnode head)

63 70 free(h);

71 h=

null;

7273 }

74 pthread_mutex_t mutex=pthread_mutex_initializer;

75 pthread_cond_t cond=pthread_cond_initializer;

76void

*runp(void

*arg)

77

9091 }

92void

*runc(void

*arg)

93 103 popfront(head,&i);

104 printf("custrom is running,data is:%d\n ",i);

105 sleep(1);

106 }

107108 }

109 int main()

110

126//for(;i>5;i--)

127//

133 pthread_join(t1,null);

134 pthread_join(t2,null);

135return

0;136 }

這裡生產者在向鍊錶中插入資料,消費者從鍊錶中讀取資料,我們通過互斥量和條件變數來控制

生產者消費者的三種關係。

來看看結果:

我們下面來利用環形佇列的資料結構來實現生產者,消費者模型,那麼先來看看環形佇列這種資料結構,和幾種約束規則。

生產者消費者訪問佇列規則:

一開始,佇列中沒有元素,必須要讓生產者先執行,消費者跟著生產者,並且消費者不能超過生產者。

生產者不能超過消費者一圈,當生產者跟消費者相遇,即佇列滿的時候,生產者必須等待消費者消費完資料,再生產。

我們發現,環形的佇列需要乙個類似於計數器的東西來記錄佇列中的節點個數,和空白節點,所以很容易就會想到訊號量的概念,通過posix訊號量,來進行執行緒的互斥和同步機制。

1

#include

2#include

3#include

4#include

5#include

6#define m 10

7#define p 3

8#define c 3

9int deque[m];

10 pthread_mutex_t mutex1=pthread_mutex_initializer;

11 pthread_mutex_t mutex2=pthread_mutex_initializer;

12 sem_t num;

13 sem_t blank;

14 void* runc(void *arg)

15

2930 }

31 void*runp(void *arg)

32

4950 }

51int main()

52 63for(i=0;i64

67for(i=0;i68

7172

for(i=0;i73

76 sem_destroy(&num);

77 sem_destroy(&blank);

78 pthread_mutex_destroy(&mutex1);

79 pthread_mutex_destroy(&mutex2);

80return

0; 81

82 }

看一下結果:

基於環形佇列的的生產者消費者模型

在linxu的多執行緒機制中,由於可能同時對臨界資源進行讀寫操作,因此互斥鎖經常被用來進行互斥操作。初次之外訊號量和環形佇列等互斥機制則使用起來更為簡單。include include include include define size 1024 環形佇列 int arr size sem t ...

基於環形佇列的生產者消費者模型編寫。

1.環形佇列 在隊列為空時,生產者必須先執行,消費者不能越過生產者 在隊列為滿時,消費者先執行,生產者不能超過消費者一圈,不能同時訪問同一位置 2.訊號量sem t sem posix的執行緒標準下的 訊號量機制通過訊號量的值控制可用資源的數量。執行緒訪問共享資源前,需要申請獲取乙個訊號量,如果訊號...

基於佇列實現生產者消費者模型

code from multiprocessing import process,queue import time,random,os def consumer q,p1 while true res q.get if res finish break time.sleep random.rand...