在生活中,我们经常去超市买东西,这里涉及到三个事物:我们、超市、供货商
我们相当于消费者,超市相当于交易场所,供货商相当于生产者
对于生产者消费者模型我们总结为3 2 1原则:
·3中关系
·2中角色
·1个交易场所
三种关系:
(1)生产者——生产者
假设所有的供货商都生产同一种产品,而超市只能由一家供货商供货,他们之间肯定互相竞争这个名额,那么可想而知他们之间存在着互斥关系
(2)消费者——消费者
如果现在超市中只有一件商品了,而所有的消费者就想去拥有这款商品,同样他们就会去互相竞争,也就是存在着互斥关系
(3)生产者——消费者
如果超市的货架上一件商品都没有我们可以消费吗?在想想超市的货架上面商品都摆的满满的,供货商还会继续摆商品吗?答案是不会,所以消费者必须等生产者生产出商品才能消费,而生产者必须等到消费者消费商品之后才能继续生产,这是典型的同步关系。同样的生产者和消费者之间还具有着互斥关系 。生产者把商品放到货架上的时候消费者不能去消费,必须等生产者放完才可以消费,而在消费者把商品从货架上拿走的时候生产者不能去放商品,必须等消费者完全拿走之后才可以放。
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<unistd.h>
4 #include<pthread.h>
5 #include<time.h>
6
7 #define CONSUMERS_COUNT 2
8 #define PRODUCERS_COUNT 2
9
10 struct msg{
11 struct msg *next;
12 int num;
13 };
14 struct msg *head = NULL;
15
16 pthread_cond_t cond;//条件变量
17 pthread_mutex_t mutex;//锁
18 pthread_t threads[CONSUMERS_COUNT + PRODUCERS_COUNT];
19
20 void *consumer(void *p)
21 {
22 int num = *(int*)p;
23 free(p);
24 struct msg *mp;
25 for(;;){
26 pthread_mutex_lock(&mutex);//上锁
27 while(head == NULL){
28 printf("%d begin wait a condition...\n",num);
29 pthread_cond_wait(&cond,&mutex);
30 }
31 printf("%d end wait a condition...\n",num);
32 printf("%d begin consume product...\n",num);
33 mp = head;
34 head = mp->next;
35 pthread_mutex_unlock(&mutex);//解锁
36 printf("Consume %d\n",mp->num);
37 free(mp);
38 printf("%d end consume product...\n",num);
39 sleep(rand()%5);
40 }
41 }
42 void *producer(void *p)
43 {
44 struct msg *mp;
45 int num = *(int*)p;
46 free(p);
47 for(;;){
48 printf("%d begin produce prodect...\n",num);
49 mp = (struct msg*)malloc(sizeof(struct msg));
50 mp->num = rand()%1000 + 1;
51 printf("produce %d\n",mp->num);
52 pthread_mutex_lock(&mutex);
53 mp->next = head;
54 head = mp;
55 printf("%d end produce product...\n",num);
56 pthread_cond_signal(&cond);
57 pthread_mutex_unlock(&mutex);
58 sleep(rand()%5);
59
60 }
61 }
62
63 int main()
64 {
65 srand(time(NULL));
66
67 pthread_cond_init(&cond,NULL);//初始化条件变量
68 pthread_mutex_init(&mutex,NULL);//初始化锁
69
70 int i;
71 for(i = 0;i < CONSUMERS_COUNT;i++){
72 int *p = (int*)malloc(sizeof(int));
73 *p = i;
74 pthread_create(&threads[i],NULL,consumer,(void*)p);//创建消费者线程
75 }
76
77 for(i = 0;i < PRODUCERS_COUNT; i++){
78 int *p = (int*)malloc(sizeof(int));
79 *p = i;
80 pthread_create(&threads[CONSUMERS_COUNT + i],NULL,producer,(void*)p);//创建生产者线程
81 }
82
83 for(i = 0; i < CONSUMERS_COUNT + PRODUCERS_COUNT; i++){
84 pthread_join(threads[i],NULL);//线程等待
85 }
86 pthread_mutex_destroy(&mutex);
87 pthread_cond_destroy(&cond);
88 }
上述生产者消费者模型是利用单链表模拟的交易场所实现的。我们还可以基于环形队列实现生产者消费者模型。
环形队列的概念:环形队列是一段连续的空间,我们很容易就可以想到数组也是一段连续的空间,所以利用数组和模运算就很容易模拟环形队列了。
基于环形队列的生产者消费者模型需要遵守的原则:
1、生产者必须走在消费者之前
2、生产者虽然先走,但不能套圈消费者
3、当队列为空时,生产者先走
当队列为满时,消费者先走