生产者与消费者
1、生产者与消费者问题
空间满:生产者不能生产数据;
空间空:消费者不能取出数据;
在这种模型下,将会有(生产者:消费者)为:一对一、一对多、多对一、多对多。
为了简化问题,在这里就只实现一个生产者和一个消费者的问题。
模型如下
注意:
(1)、线程阻塞时,用条件变量来解决。唤醒并运行其后的语句是在遇到阻塞之后;
(2)、临界区模式;
pthread_mutex_lock(&mutex);
//临界区
pthread_cond_wait(&cond, &mutex); //该函数将自动解锁,此处将会发生阻塞。
......
pthread_mutex_unlock(&mutex);
(3)、本题还可以采用双缓冲区;
2、代码实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<string.h> #include<pthread.h> #define BUF_SIZE 8 //一个开辟8个数组元素空间 #define MAX_NUM 20 //将一共产生20个数据 struct PC{ //生产者与消费者结构体
pthread_mutex_t mutex; //互斥量
pthread_cond_t noempty; //条件变量,数组不空
pthread_cond_t nofull; //条件变量,数组不满
int buf[BUF_SIZE]; //开辟空间
int nput; //数组下标
int nval; //要存放的数据
int size; //统计当前数组空间大小
}shared = {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER}; void * producer( void *arg){
for (;;){
pthread_mutex_lock(&shared.mutex);
if (shared.nval > MAX_NUM){
pthread_mutex_unlock(&shared.mutex);
break ;
}
shared.buf[shared.nput] = shared.nval;
shared.nput++;
shared.nval++;
shared.size++;
if (shared.nput >= BUF_SIZE){
shared.nput = 0; //下标始终在0-7
}
if (shared.size >= BUF_SIZE){
pthread_cond_wait(&shared.nofull, &shared.mutex);
} else {
pthread_cond_signal(&shared.noempty);
}
pthread_mutex_unlock(&shared.mutex);
}
} void *customer( void *arg){
int value;
int i = 0;
for (;;){
pthread_mutex_lock(&shared.mutex);
value = shared.buf[i];
i++;
printf ( "value = %d\n" , value);
if (value >= MAX_NUM){
pthread_mutex_unlock(&shared.mutex);
break ;
}
sleep(1);
if (i >= BUF_SIZE){
i = 0;
}
shared.size--;
if (shared.size == 0){
pthread_cond_wait(&shared.noempty, &shared.mutex);
} else {
pthread_cond_signal(&shared.nofull);
}
pthread_mutex_unlock(&shared.mutex);
}
} void initPc( void ){ //对结构体成员初始化
memset (shared.buf, 0, BUF_SIZE);
shared.nput = 0; //下标从0开始
shared.nval = 1; //存放的数据从1开始
shared.size = 0; //数组空间大小为0
} int main( void ){
initPc();
pthread_t pid, cid;
pthread_create(&pid, NULL, producer, NULL);
pthread_create(&cid, NULL, customer, NULL);
pthread_join(pid, NULL);
pthread_join(cid, NULL);
return 0;
} |
运行结果
对以上的代码模式解读:首先是生产者生产,在空间满了之后,阻塞等待,此时,消费者在读取数据,等到读取为空的时候,唤醒生产者生产,最后,在生产完了的时候,消费者读取完成,将一起退出for循环。
这里的同步就是利用了锁机制完成的(通过互斥量和条件变量)。