如圖:一共有三種關係:生產者與生產者的互斥關係,消費者與消費者的互斥關係,生產者與消費者的互斥且同步關係。
兩種角色:生產者(執行緒)與消費者(執行緒)
乙個交易場所:倉庫(一段記憶體空間,且可存可取)
二、基於單向鍊錶的生產者消費者模型
1、我們這裡用乙個單鏈表當做那段共享記憶體,簡單實現生產者消費者模型。
**:
1 #include2 #include3 #include4 #include5
6 typedef struct nodenode_t,*node_p,**node_pp;
10 11 node_p allocnode(int x)
17 18 p->data=x;
19 p->next=null;
20 return p;
21 }
22 23 int isempty(node_p head)
28 29 void initlist(node_pp head)
32 33 void listpush(node_p head,int x)
38 39 int listpop(node_p head,int *x)
47 free(p);
48 ret=0;
49 }
50 return ret;
51 }
52 53 void showlist(node_p head)
60 }
61 printf("\n");
62 }
63 64 void destroylist(node_p head)
68 }
2、鎖
同步的最常見方法是使用鎖,鎖是一種非強制機制,每乙個執行緒在訪問資料或資源之前先試圖獲取鎖,並在訪問結束之後釋放鎖,在鎖已經被占用時試圖獲取鎖時,執行緒會等待,直到鎖重新可用。
看一下有關函式
lock用巨集初始化。
pthread_mutex_t lock=pthread_mutex_initializer;
3、條件變數
4、完整**如下:
由於生產者和消費者的互斥與相關,在無資料取出時需要消費者等待,在生產過多資料未處理時,要存在緩衝區。
1 #include2 #include3 #include4 #include5
6 typedef struct nodenode_t,*node_p,**node_pp;
10 11
12 pthread_mutex_t lock=pthread_mutex_initializer;
13 pthread_cond_t cond=pthread_cond_initializer;
14 15 node_p allocnode(int x)
21 22 p->data=x;
23 p->next=null;
24 return p;
25 }
26 27 int isempty(node_p head)
32 33 void initlist(node_pp head)
36 37 void listpush(node_p head,int x)
42 43 int listpop(node_p head,int *x)
51 free(p);
52 ret=0;
53 }
54 return ret;
55 }
56 57 void showlist(node_p head)
64 }
65 printf("\n");
66 }
67 68 void destroylist(node_p head)
72 }
73 74 void *runp(void *arg)
86 }
87 88 void *runc(void *arg)else
100 pthread_mutex_unlock(&lock);
101 sleep(1);
102 }
103 }
104
105 int main()
124
125 for(;i>5;i--)
129
130 destroylist(head);
131 return 0;
132 }
結果如下:我們可以在**中調整生產者消費者的等待時間,看結果的不同
三、基於環形佇列的生產者消費者模型
1、posix訊號量
posix訊號量和systemv訊號量作相同,都是用於同步操作,達到無衝突的訪問共享資源目的。 但posix 可以用於執行緒間同步。
在使用訊號量之前,必須對其進行初始化:
引數:value 為訊號量的初始值
pshared用於說明訊號量的共享範圍,如果pshared 為0,那麼該訊號量只能由初始化這個訊號量的程序中的執行緒使用,如果pshared 非零,任何可以訪問到這個訊號量的程序都可以使用這個訊號量。
函式sem_destroy 銷毀乙個指定的訊號量:
等待訊號量函式:
功能:等待訊號量,會將訊號量的值減1
發布訊號量
功能:發布訊號量,表示資源使用完畢,可以歸還資源了。將訊號量值加1。
上一節生產者-消費者的例子是基於鍊錶的,其空間可以動態分配,現在基於固定大小的環形佇列重寫這個程式 (posix訊號量):
1 #include2 #include3 #include4 #include5
6 #define m 10
7 int ring[m];
8 9 sem_t semblank;
10 sem_t semdata;
11 12 void *runc(void *arg)
24 }
25 26 void *runp(void *arg)
39 }
40 41 int main()
結果: 生產者與消費者模型
先介紹幾個函式 生產消費者模型 二者共享資料value,這裡,生產者是producter,消費者是consumer。生產者負責放物品到value中,消費者使用wait 等待生產者的通知。當得到通知後,消費者取出物品,並且用notify 通知生產者,可以再放下一批物品。例項 package cn.ed...
生產者與消費者模型
生產者 消費者模型描述的是有一塊緩衝區作為倉庫,生產者可將產品放入倉庫,消費者可以從倉庫中取出產品,模型圖如下所示 1 三種關係 三種關係分別指的是 消費者和消費者,生產者和生產者,生產者和消費者 其中消費者和消費者,生產者和生產者之間都屬於競爭關係,生產者和消費者之間的關係相當於是一種食物鏈之間的...
生產者與消費者模型
一種場所,兩種角色,三種關係 功能 解耦合,支援忙閒不均,支援併發 stl std queue 非執行緒安全 class blockqueue queuepush int data 整合執行緒安全的入隊操作 queuepop int data 整合執行緒安全的出隊操作 手撕生產者與消費者模型 實現執...