在生产者/消费者模型中,生产者Producer负责生产数据,而消费者Consumer负责使用数据。多个生产者线程会在同一时间运行,生产数据放到内存中一个共享的数据缓冲区域。然后多个消费者线程读取内存共享的数据缓冲区域。如果生产者超前消费者,共享数据缓冲区满了,则生产者暂停写入等待读取。如果消息者超前生产者,则消费者暂停读取等待写入。
例程:多个生产者线程,多个消费者线程,生产对整数数组buff写入,buff[i]=i,消费者验证每个数组元素都是正确的
1 #include <unistd.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <pthread.h>
5 #define MAXNITEMS 10000000
6 #define MAXNTHREADS 100
7 int nitems;
8 struct {
9 pthread_mutex_t mutex;//定义互斥锁
10 int buff[MAXNITEMS];//公共数据缓冲区,共享数组
11 int nput;//生产者下一次存放到buff数组中的下标
12 int nval;//生产者下一次存放到buff数组的值
13 }shared={PTHREAD_MUTEX_INITIALIZER};//通过宏初始化互斥锁
14 void* produce(void* arg){
15 for(;;){
16 pthread_mutex_lock(&shared.mutex);//加锁
17 if(shared.nput>=nitems){//如果生产计数超过缓冲区容量,停止生产
18 pthread_mutex_unlock(&shared.mutex);//减锁
19 return(NULL);/*array is full,we're done*/
20 }
21 shared.buff[shared.nput]=shared.nval;//生产者往缓冲区写入数据
22 shared.nput++;//下标增加1
23 shared.nval++;//值增加1
24 pthread_mutex_unlock(&shared.mutex);
25 *((int* )arg)+=1;//计数增加1
26 }
27 }
28 //判断是是否可以从共享数据缓冲区中读取
29 void consume_wait(int i){
30 for(;;){
31 pthread_mutex_lock(&shared.mutex);
32 if(i<shared.nput){//生产者下一次存放的下标大于0,说明共享数组不为空,解锁返回,消费者可以进行验证工作
33 pthread_mutex_unlock(&shared.mutex);
34 return;
35 }
36 //共享数组为空时,消费者轮询等待
37 pthread_mutex_unlock(&shared.mutex);
38
39 }
40
41 }
42 void* consume(void *arg){
43 int i;
44 for(i=0;i<nitems;i++){//生产者下一次存放的下标
45 consume_wait(i);
46 if(shared.buff[i]!=i)
47 printf("buff[%d]=%d\n",i,shared.buff[i]);
48 *((int*)arg)+=1;//生产者计数增加1
49 }
50
51 return NULL;
52 }
53
54 int main(int argc,char **argv){
55 int i,nthreads,count[MAXNTHREADS];//定义循环变量,线程个数存储变量,各个线程执行存放数/读取目计数变量
56 pthread_t tid_produce[MAXNTHREADS],tid_consume[5];//定义生产者线程ID和消费者线程ID
57 if(argc!=3){
58 printf("usage:prodcons2 <#items><#thread>");
59 exit(-1);
60 }
61 nitems=atoi(argv[1]);//生产者存放的条目数
62 nthreads=atoi(argv[2]);//待创建生产者线程的数目
63 pthread_setconcurrency(nthreads+1);//告诉系统我们希望并发运行多少线程
64 //启动所有的生产者和消费者线程
65 for(i=0;i<nthreads;i++){
66 count[i]=0;
67 pthread_create(&tid_produce[i],NULL,produce,&count[i]);
68 }
69 for(i=0;i<5;i++){
70 count[i]=0;
71 pthread_create(&tid_consume[i],NULL,consume,&count[i]);
72
73 }
74 //等待生产者和消费者线程
75 printf("生产者:\n");
76 for(i=0;i<nthreads;i++){
77 pthread_join(tid_produce[i],NULL);
78 printf("count[%d]=%d\n",i,count[i]);
79 }
80 printf("消费者:\n");
81 for(i=0;i<5;i++){
82 pthread_join(tid_consume[i],NULL);
83 printf("count[%d]=%d\n",i,count[i]);
84 }
85 exit(0);
86
87 }
88
编译运行结果如下:
UC#./prodcons 1000000 5
生产者:
count[0]=407079
count[1]=503909
count[2]=583584
count[3]=704752
count[4]=850602
消费者:
count[0]=1086730
count[1]=1182059
count[2]=1282185
count[3]=1201515
count[4]=1247511