Classic of operating system | producer and consumer problems

1, Overview of producer consumer issues

Description: two or more threads share the same buffer. One or more threads as a "producer" will constantly add data to the buffer, and the other or more threads as a "consumer" will take data from the buffer. Note the following:

  • Producers and consumers must use buffers that are mutually exclusive
  • The consumer cannot read data when the buffer is empty
  • The producer cannot add data when the buffer is full

2, Advantages of producer consumer model

1. Decoupling: because there is an additional buffer, producers and consumers do not call each other directly. In this way, changes in the codes of producers and consumers will not affect each other. In fact, this is to untie the strong coupling between producers and consumers, and become the weak coupling between producers and buffers, consumers and buffers

2. Support Concurrency: if the consumer takes data directly from the producer, the consumer needs to wait for the producer's production data. Similarly, the producer needs to wait for the consumer's consumption data.

With the producer / consumer model, producer and consumer can be two independent concurrent subjects. The producer adds the manufactured data to the buffer and can produce the next data.

The same is true for consumers. They don't need to wait for producers to read data from the buffer. In this way, producers and consumers can execute concurrently.

3. Support uneven busy and idle: if consumers get data directly from producers, and producers' production data is very slow, consumer consumption data is very fast, or producers produce a lot of data, consumer consumption data is very slow. Will result in a waste of CPU time.

In the producer / consumer model, the producer only needs to add the production data to the buffer, and the buffer will not be produced when it is full. Consumers read data from the buffer, and the buffer will not consume when it is empty, so that the processing capacity of producers / consumers reaches a dynamic balance.

3, Producer consumer model variable definition

definition:
sem_empty (represents whether the buffer is free) to judge whether the producer can write data to the buffer. The initial value is n

sem_full (representing how much data there is in the buffer) to judge whether the consumer can read data from the buffer. The initial value is 0

Because the consumer cannot read when the producer writes data to the buffer, it is necessary to define a mutex

4, Producer consumer flow chart


producer:
The order cannot be changed

consumer:

5, Code

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<pthread.h>
#include<semaphore.h>

#define BUFF_MAX 10
#define SC_NUM 2
#define XF_NUM 3

int buff[BUFFMAX];
int in = 0;
int out = 0;

sem_t sem_empty;//Semaphore
sem_t sem_full;//Semaphore
pthread_mutex_t mutex;

void *sc_thread(coid *arg)
{
	int index = (int)arg;
	for(int i = 0; i < 30; i++)
	{
		sem_wait(&sem_empty);//See if there's any free space. p minus one
		pyhread_mutex_lock(&mutex);//Lock
		buff[in] = rand() % 100;
		printf("The first%d Data generated by threads:%d,stay%d Location of\n",index,buff[in],in);
		in = (in + 1) % BUFF_MAX;
		 pthread_mutex_unlock(&mutex);
		 sem_post(&sem_full);//Number of data v Plus One
			
		
	}
}

void * xf_thread(void *arg)
{
	int index = (int)arg;
	for(int i = 0;i < 20; i++)
	{
		sem_wait(&sem_full);
		pthread_mutex_lock(&mutex);
		printf("---------The first%d Threads consuming data:%d,stay%d position\n",index,buff[out],out);
		out = (out + 1) % BUFF_MAX;
		pthread_mutex_unlock(&mutex);
		sem_post(&sem_empty);
	}
}

int main()
{
	sem_init(&sem_empty,0,0,BUFF_MAX);//Semaphore initialization
	sem_init(&sem_full,0,0);//Semaphore initialization
	pthread_mutex_init(&mutex,NULL);
	
	srand((int))time(NULL);
	
	pthread_t sc_id[SC_NUM];//Define producer
	pthread_t xf_id[XF_NUM];//Define consumer

	for(int i = 0;i < SC_NUM;i++)
	{
		pthread_create(	&sc_id[i],NULL,sc_thread,(void*)i);//Create producer
	}

	for(int i = 0; i < XF_NUM; i++)
	{
		pthread_create(&xf_id[i],NULL,xf_thread,(void*)i);//Create consumer
	}
	
	for(int i = 0;i < SC_NUM;i++)
	{
		pthread_join(&sc_id[i],NULL);
	}

	for(int i = 0; i < XF_NUM; i++)
	{
		pthread_join(&xf_id[i],NULL);
	}
	
	//Destroy semaphore
	sem_destroy(&sem_empty);
	sem_destrory(&sem_full);

	//Mutex destruction
	pthread_mutex_destroy(&mutex);
		
	printf("main over\n");
	exit(0);
}

Tags: Java C kafka RabbitMQ Operating System

Posted on Sun, 05 Dec 2021 13:33:42 -0500 by gingerboy101