Producer Consumer Problem and its Implementation with C++

31 May, 2021
Overview :In this article, we will discuss the Producer-Consumer Problem and its Implementation with C++. The Producer-Consumer problem is a classical two-process synchronization problem. Let’s discuss it one by one.
Problem Statement :There is one Producer and one Consumer in the producer-consumer problem.
Producer – The producer process executes a set of statements int produce to create a data element and stores it in the buffer.Consumer – If the buffer has items, a consumer process executes a statement consume with the data element as a parameter.
Producer – The producer process executes a set of statements int produce to create a data element and stores it in the buffer.
Consumer – If the buffer has items, a consumer process executes a statement consume with the data element as a parameter.
Solution :  The problem arises because the process is not synchronized because of which the items produced and consumed may not be consistent. In order to solve this problem, we use semaphore for solving this problem i.e. problem of the critical section.
Implementation in C++ :This problem can be further subdivided into two parts as follows.
Part-1: Where the buffer size is infinite –In this case, the buffer from where the producer stores the item and the consumer consumes the item size is not fixed.
C++14
#include<bits/stdc++.h>#include<pthread.h>#include<semaphore.h>#include <unistd.h> using namespace std;  // Declarationint r1,total_produced=0,total_consume=0;  // Semaphore declarationsem_t notEmpty;  // Producer Sectionvoid* produce(void *arg){    while(1){      cout<<"Producer produces item."<<endl;      cout<<"Total produced = "<<++total_produced<<        " Total consume = "<<total_consume*-1<<endl;      sem_post(¬Empty);          sleep(rand()%100*0.01);    }}  // Consumer Sectionvoid* consume(void *arg){    while(1){      sem_wait(¬Empty);      cout<<"Consumer consumes item."<<endl;          cout<<"Total produced = "<<total_produced<<        " Total consume = "<<(--total_consume)*-1<<endl;      sleep(rand()%100*0.01);    }    }  int main(int argv,char *argc[]){      // thread declaration    pthread_t producer,consumer;      // Declaration of attribute......    pthread_attr_t attr;      // semaphore initialization    sem_init(¬Empty,0,0);      // pthread_attr_t initialization    pthread_attr_init(&attr);    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);      // Creation of process    r1=pthread_create(&producer,&attr,produce,NULL);    if(r1){      cout<<"Error in creating thread"<<endl;      exit(-1);    }      r1=pthread_create(&consumer,&attr,consume,NULL);    if(r1){      cout<<"Error in creating thread"<<endl;      exit(-1);    }      // destroying the pthread_attr    pthread_attr_destroy(&attr);      // Joining the thread    r1=pthread_join(producer,NULL);    if(r1){      cout<<"Error in joining thread"<<endl;      exit(-1);    }      r1=pthread_join(consumer,NULL);    if(r1){      cout<<"Error in joining thread"<<endl;      exit(-1);    }      // Exiting thread    pthread_exit(NULL);      return 0;}
Part-2: Where the buffer size is fixed or finite –In this case, the buffer from where the producer stores the item and the consumer consumes the item size is fixed.
C++14
#include <bits/stdc++.h>#include <pthread.h>#include <semaphore.h>#include <unistd.h>using namespace std;  // Declarationint r1, items = 0;  // Semaphore declarationsem_t notEmpty, notFull;  // Producer Sectionvoid* produce(void* arg){    while (1) {        sem_wait(¬Full);        sleep(rand() % 100 * 0.01);        cout <<       "Producer produces item.Items Present = "             << ++items << endl;        sem_post(¬Empty);        sleep(rand() % 100 * 0.01);    }}  // Consumer Sectionvoid* consume(void* arg){    while (1) {        sem_wait(¬Empty);        sleep(rand() % 100 * 0.01);        cout <<      "Consumer consumes item.Items Present = "             << --items << endl;        sem_post(¬Full);        sleep(rand() % 100 * 0.01);    }}  int main(int argv, char* argc[]){      int N;    cout <<       "Enter the capacity of the buffer" << endl;    cin >> N;      // thread declaration    pthread_t producer, consumer;      // Declaration of attribute......    pthread_attr_t attr;      // semaphore initialization    sem_init(¬Empty, 0, 0);    sem_init(¬Full, 0, N);      // pthread_attr_t initialization    pthread_attr_init(&attr);    pthread_attr_setdetachstate(&attr,             PTHREAD_CREATE_JOINABLE);      // Creation of process    r1 = pthread_create(&producer, &attr,                         produce, NULL);    if (r1) {        cout <<           "Error in creating thread" << endl;        exit(-1);    }      r1 = pthread_create(&consumer, &attr,                         consume, NULL);    if (r1) {        cout <<           "Error in creating thread" << endl;        exit(-1);    }      // destroying the pthread_attr    pthread_attr_destroy(&attr);      // Joining the thread    r1 = pthread_join(producer, NULL);    if (r1) {        cout << "Error in joining thread" << endl;        exit(-1);    }      r1 = pthread_join(consumer, NULL);    if (r1) {        cout << "Error in joining thread" << endl;        exit(-1);    }      // Exiting thread    pthread_exit(NULL);      return 0;}
GATE CS
Operating Systems
Operating Systems
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Difference between Clustered and Non-clustered index
Introduction of Process Synchronization
Three address code in Compiler
Differences between IPv4 and IPv6
Phases of a Compiler
Banker's Algorithm in Operating System
Disk Scheduling Algorithms
Introduction of Deadlock in Operating System
Paging in Operating System
File Allocation Methods