Multithreading Programming Series (5): "Producer-Consumer" Experiment — Implementation Using PV Primitives
#Multithreading#Programming#Null#Thread#Join#Product
I. Problem Description
There is a bounded buffer and two threads: producer and consumer. The producer writes products into the buffer, while the consumer removes them. When the buffer is full, the producer must wait before writing; when the buffer is empty, the consumer cannot read and must wait.
II. Example
/*product.c*/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <sys/ipc.h>#include <semaphore.h>#include <fcntl.h>#include <pthread.h>#define FIFO "myfifo"#define N 5int lock_var;time_t end_time;char buf_r[100];sem_t mutex,full,avail;int fd;void productor(void *arg);void consumer(void *arg); int main(int argc,char *argv[]){ pthread_t id1,id2; pthread_t mon_th_id; int ret; end_time = time(NULL)+30; /*create namepipe*/ if((mkfifo(FIFO,O_CREAT|O_EXCL)<0) && (errno != EEXIST)) printf("cannot create fifoserver\n"); printf("preparing for reading bytes..."); memset(buf_r,0,sizeof(buf_r)); /*open pipe*/ fd = open(FIFO,O_RDWR | O_NONBLOCK,0); if(fd == -1){ perror("open"); exit(1); } /*init sem valuable*/ ret = sem_init(&mutex,0,1); ret = sem_init(&avail,0,N); ret = sem_init(&full,0,0); if(ret != 0){ perror("sem_init"); } /*create 2 pthread*/ ret = pthread_create(&id1,NULL,(void *)productor,NULL); if(ret != 0) perror("pthread_cread1"); ret = pthread_create(&id2,NULL,(void *)consumer,NULL); if(ret != 0) perror("pthread_cread2"); pthread_join(id1,NULL); pthread_join(id2,NULL); exit(0);} /*product thread*/void productor(void *arg){ int i,nwrite; while(time(NULL) < end_time){ /*p operate to the avail,mutex*/ sem_wait(&avail); sem_wait(&mutex); /*productor write data to the pipe*/ if((nwrite = write(fd,"hello",5)) == -1){ if(errno == EAGAIN) printf("the FIFO has not been read yet,please try later\n"); } else printf("write hello to the FIFO\n"); /*v opertate to full,mutex*/ sem_post(&full); sem_post(&mutex); sleep(1); }} /*consumer thread*/void consumer(void *arg){ int nolock = 0; int ret,nread; while(time(NULL) < end_time){ sem_wait(&full); sem_wait(&mutex); memset(buf_r,0,sizeof(buf_r)); if(nread = read(fd,buf_r,100) == -1){ if(errno = EAGAIN) printf("no data yet\n"); } printf("read %s from FIFO\n",buf_r); sem_post(&avail); sem_post(&mutex); sleep(1); }}
Execution result:
[root@localhost net]# ./productpreparing for reading bytes...write hello to the FIFOread hello from FIFOwrite hello to the FIFOread hello from FIFOwrite hello to the FIFOread hello from FIFOwrite hello to the FIFOread hello from FIFOwrite hello to the FIFOread hello from FIFOwrite hello to the FIFOread hello from FIFO