Producer–Consumer Problem Using Semaphores (Bounded Buffer)

 

Producer–Consumer Problem Using Semaphores (Bounded Buffer)

This introduces multiple producers, multiple consumers, and uses three semaphores:

  • empty, full, mutex
    It is a classic synchronization problem demonstrating mutual exclusion + synchronization.


1. AIM

To implement the Producer–Consumer Problem using semaphores, ensuring proper synchronization between producers and consumers in a bounded buffer.


2. OBJECTIVE

  • To understand inter-process communication and synchronization.

  • To manage a shared circular buffer with multiple producers and consumers.

  • To use semaphores to prevent race conditions, buffer overflow, and buffer underflow.


3. THEORY

The Producer–Consumer Problem

  • Producer generates data and puts it into a buffer.

  • Consumer removes data from the buffer.

  • If the buffer is full, producers must wait.

  • If the buffer is empty, consumers must wait.

  • A mutex semaphore ensures only one process modifies the buffer at a time.

Semaphores Used

Semaphore        Purpose
mutex        Mutual exclusion on buffer
empty        Counts empty slots (producer waits when 0)
full                Counts full slots (consumer waits when 0)

Concepts introduced in this experiment

✔ Bounded buffer
✔ Circular queue
✔ Producer and Consumer threads
✔ Counting semaphores
✔ Mutual exclusion + synchronization
✔ Handling race conditions



4. ALGORITHM

Producer Algorithm

repeat forever:
produce item
wait(empty) // wait for empty slot
wait(mutex) // lock buffer

insert item into buffer

signal(mutex) // release lock
signal(full) // one more full slot

Consumer Algorithm

repeat forever:
wait(full) // wait for available item
wait(mutex) // lock buffer

remove item from buffer

signal(mutex) // release lock
signal(empty) // one more empty slot
consume item

5. C PROGRAM (Producer–Consumer with Bounded Buffer)

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>
#define BUFFER_SIZE 5

int buffer[BUFFER_SIZE];
int in = 0, out = 0;
sem_t empty, full, mutex;

void* producer(void* arg) {
int item;
int id = *(int*)arg;
while (1) {
item = rand() % 100;
sem_wait(&empty); // Wait for empty slot
sem_wait(&mutex); // Enter critical section

buffer[in] = item;
printf("Producer %d produced %d at buffer[%d]\n", id, item, in);
in = (in + 1) % BUFFER_SIZE;

sem_post(&mutex); // Exit critical section
sem_post(&full); // Increase full count
sleep(1);
}
}

void* consumer(void* arg) {
int item;
int id = *(int*)arg;
while (1) {

sem_wait(&full); // Wait for full slot
sem_wait(&mutex); // Enter critical section

item = buffer[out];
printf(" Consumer %d consumed %d from buffer[%d]\n", id, item, out);
out = (out + 1) % BUFFER_SIZE;

sem_post(&mutex); // Exit critical section
sem_post(&empty); // Increase empty count
sleep(2);
}
}


int main() {
pthread_t prod[3], cons[3];
int ids[3] = {1, 2, 3};
sem_init(&mutex, 0, 1);
sem_init(&empty, 0, BUFFER_SIZE);
sem_init(&full, 0, 0);
for (int i = 0; i < 3; i++) {
pthread_create(&prod[i], NULL, producer, &ids[i]);
pthread_create(&cons[i], NULL, consumer, &ids[i]);
}
for (int i = 0; i < 3; i++) {
pthread_join(prod[i], NULL);
pthread_join(cons[i], NULL);
}
sem_destroy(&mutex);
sem_destroy(&empty);
sem_destroy(&full);
return 0;
}

6. SAMPLE OUTPUT

binuvp@debian-workstation:~$ gcc producer.c
binuvp@debian-workstation:~$ ./a.out
Producer 1 produced 83 at buffer[0]
Producer 2 produced 86 at buffer[1]
    Consumer 2 consumed 83 from buffer[0]
Producer 3 produced 77 at buffer[2]
    Consumer 3 consumed 86 from buffer[1]
    Consumer 1 consumed 77 from buffer[2]
Producer 1 produced 15 at buffer[3]
Producer 2 produced 93 at buffer[4]
Producer 3 produced 35 at buffer[0]
    Consumer 2 consumed 15 from buffer[3]
    Consumer 3 consumed 93 from buffer[4]
    Consumer 1 consumed 35 from buffer[0]
Producer 1 produced 86 at buffer[1]
Producer 2 produced 92 at buffer[2]
Producer 3 produced 49 at buffer[3]
Producer 1 produced 21 at buffer[4]
Producer 3 produced 62 at buffer[0]

7. RESULT

The producer-consumer problem using semaphores was successfully implemented.
The program ensures proper synchronization between producer and consumer threads and prevents buffer underflow and overflow.

Comments

Popular posts from this blog

Operating Systems OS Lab PCCSL407 Semester 4 KTU BTech CS 2024 Scheme - Dr Binu V P

Exploring the /proc file system

ps command