基本结构与多生产者,单消费者模式一样.详见代码.
/* include main */
#include <iostream>
#include <stdio.h>
#include <pthread.h>
#include <stdint.h>
#include "stdlib.h"
#include <semaphore.h>
#include <unistd.h>
#include <string>
#define NBUFF 10
#define MAXNTHREADS 100
#define min(a , b) ( (a) < (b) ? (a) : (b))
using namespace std;
int nitems, nproducers,nconsumers; /* read-only by producer and consumer */
struct { /* data shared by producers and consumer */
int buff[NBUFF];
int nput;
int nputval;
int nget;//一个消费者线程带取出的下一条目的编号
int ngetval;//存放相应位置的值.
sem_t mutex, nempty, nstored; /* semaphores, not pointers */
} shared;
void *produce(void *), *consume(void *);
int
main(int argc, char **argv)
{
printf("shared's int value nput = %d,nputval= %d,nget = %d,ngetval = %d \n",shared.nput,shared.nputval,shared.nget,shared.ngetval);//int 全局变量,会默认初始化为0,因此没有看到shared结构体对他们的初始化.
int i, prodcount[MAXNTHREADS],conscount[MAXNTHREADS];
pthread_t tid_produce[MAXNTHREADS], tid_consume[MAXNTHREADS];
if (argc != 4)
{
printf("usage: prodcons3 <#items> <#producers>\n");
return 0;
}
nitems = atoi(argv[1]);
nproducers = min(atoi(argv[2]), MAXNTHREADS);
nconsumers = min(atoi(argv[3]), MAXNTHREADS);
/* 4initialize three semaphores */
sem_init(&shared.mutex, 0, 1);
sem_init(&shared.nempty, 0, NBUFF);
sem_init(&shared.nstored, 0, 0);
/* 4create all producers and one consumer */
// set_concurrency(nproducers + 1);
for (i = 0; i < nproducers; i++) {
prodcount[i] = 0;
pthread_create(&tid_produce[i], NULL, produce, &prodcount[i]);
}
for (i = 0; i < nconsumers; i++) {
conscount[i] = 0;
pthread_create(&tid_consume[i], NULL, consume, &conscount[i]);
}
/* 4wait for all producers and the consumer */
for (i = 0; i < nproducers; i++) {
pthread_join(tid_produce[i], NULL);
printf("proder count[%d] = %d\n", i, prodcount[i]);
}
for (i = 0; i < nconsumers; i++) {
pthread_join(tid_consume[i], NULL);
printf("consumer count[%d] = %d\n", i, conscount[i]);
}
sem_destroy(&shared.mutex);
sem_destroy(&shared.nempty);
sem_destroy(&shared.nstored);
exit(0);
}
/* end main */
/* include produce */
void *
produce(void *arg)
{
for ( ; ; ) {
sem_wait(&shared.nempty); /* wait for at least 1 empty slot */
sem_wait(&shared.mutex);
if (shared.nput >= nitems) {
sem_post(&shared.nstored);//因为消费者阻塞在,sem_wait()中,当所有的生产者线程完成后,让nstored加1,给各个消费者线程解阻塞.
sem_post(&shared.nempty);
sem_post(&shared.mutex);
return(NULL); /* all done */
}
shared.buff[shared.nput % NBUFF] = shared.nputval;
shared.nput++;
shared.nputval++;
sem_post(&shared.mutex);
sem_post(&shared.nstored); /* 1 more stored item */
*((int *) arg) += 1;
}
}
/* end produce */
/* include consume */
void *
consume(void *arg)
{
for(;;)
{
sem_wait(&shared.nstored); /* wait for at least 1 stored item */
sem_wait(&shared.mutex);
if (shared.nget >= nitems) { //消费者比较nget与nitems,确定消费者线程完成消费工作的时刻
sem_post(&shared.nstored);
sem_post(&shared.mutex);
return(NULL); /* all done */
}
shared.nget++;
shared.ngetval++;
sem_post(&shared.mutex);
sem_post(&shared.nempty); /* 1 more stored item */
*((int *) arg) += 1;
}
}
/* end consume */
对应的Makefile:
CC = g++
CFLAGS = -std=c++11
PROGS = mul-pro-1con mul-pro-mul-con
LIBS = -lpthread
all: ${PROGS}
mul-pro-1con: mul-pro-1con.o
${CC} ${CFLAGS} -o $@ mul-pro-1con.o ${LIBS}
mul-pro-mul-con: mul-pro-mul-con.o
${CC} ${CFLAGS} -o $@ mul-pro-mul-con.o ${LIBS}
clean:
rm -f ${PROGS} ${CLEANFILES}