Powered By Blogger

Aug 6, 2024

Operating System Lab Practical-10

 

Practical-10

Title : Implementation of Producer- Consumer problem using semaphores

—---------------------------------------------------------------------------------------------------------------

The Producer-Consumer problem is a classic synchronization problem that illustrates the challenges of resource sharing between multiple processes. It involves two main types of processes: producers, which generate data to be stored in a shared buffer, and consumers, which take data from the buffer for further processing. The challenge is to ensure that producers and consumers access the buffer in a synchronized manner to avoid issues such as data corruption, race conditions, and deadlocks.

In this problem, semaphores are used to manage access to the shared buffer, ensuring that producers do not write to a full buffer and consumers do not read from an empty buffer. We'll use three semaphores:

  1. empty: Represents the number of empty slots available in the buffer.

  2. full: Represents the number of filled slots available in the buffer.

  3. mutex: Ensures mutual exclusion while accessing the buffer.

Here's a step-by-step ALGORITHM  of the Producer-Consumer problem using semaphores:


Initialization

  1. Define Constants:

    • BUFFER_SIZE: Size of the shared buffer.

    • MAX_ITEMS: Number of items to be produced/consumed.

  2. Initialize Buffer and Indices:

    • buffer: Array of size BUFFER_SIZE to hold items.

    • in: Integer to track the next index to insert an item (in = 0).

    • out: Integer to track the next index to remove an item (out = 0).

  3. Initialize Semaphores and Mutex:

    • empty: Counting semaphore, initialized to BUFFER_SIZE.

    • full: Counting semaphore, initialized to 0.

    • mutex: Binary semaphore (mutex), initialized to 1.


Producer Process

Repeat until all items are produced:

  1. Produce an Item:

    • Generate a new item to be placed in the buffer.

  2. Wait for an Empty Slot:

    • wait(empty): Decrement the empty semaphore. If no empty slots are available, wait.

  3. Enter Critical Section:

    • wait(mutex): Acquire the mutex lock to ensure exclusive access to the buffer.

  4. Add Item to Buffer:

    • buffer[in] = item: Place the produced item at the current in index.

    • in = (in + 1) % BUFFER_SIZE: Update the in index using modulo operation to wrap around if necessary.

  5. Exit Critical Section:

    • signal(mutex): Release the mutex lock, allowing other threads to access the buffer.

  6. Signal a Full Slot:

    • signal(full): Increment the full semaphore to indicate a filled slot is available.

  7. Simulate Production Delay:

    • Sleep for a random or fixed duration to simulate production time.


Consumer Process

Repeat until all items are consumed:

  1. Wait for a Full Slot:

    • wait(full): Decrement the full semaphore. If no filled slots are available, wait.

  2. Enter Critical Section:

    • wait(mutex): Acquire the mutex lock to ensure exclusive access to the buffer.

  3. Remove Item from Buffer:

    • item = buffer[out]: Retrieve the item at the current out index.

    • out = (out + 1) % BUFFER_SIZE: Update the out index using modulo operation to wrap around if necessary.

  4. Exit Critical Section:

    • signal(mutex): Release the mutex lock, allowing other threads to access the buffer.

  5. Signal an Empty Slot:

    • signal(empty): Increment the empty semaphore to indicate an empty slot is available.

  6. Simulate Consumption Delay:

    • Sleep for a random or fixed duration to simulate consumption time.


Code :

#include <stdio.h>

#include <stdlib.h>

#include <pthread.h>

#include <semaphore.h>

#include <unistd.h>


// Define buffer size

#define BUFFER_SIZE 5


// Buffer array and index

int buffer[BUFFER_SIZE];

int in = 0, out = 0;


// Semaphores

sem_t empty;  // Counts empty slots in the buffer

sem_t full;   // Counts full slots in the buffer

pthread_mutex_t mutex;  // Ensures mutual exclusion for buffer access


// Function for producer thread

void* producer(void* arg) {

    int item;

    for(int i = 0; i < 10; i++) { // Produces 10 items

        item = rand() % 100;  // Produces a random item


        sem_wait(&empty);  // Wait for an empty slot

        pthread_mutex_lock(&mutex);  // Lock the buffer


        // Add item to buffer

        buffer[in] = item;

        printf("Producer produced: %d\n", item);

        in = (in + 1) % BUFFER_SIZE;  // Move index


        pthread_mutex_unlock(&mutex);  // Unlock the buffer

        sem_post(&full);  // Increase the full slot count


        sleep(1);  // Simulate production time

    }

}


// Function for consumer thread

void* consumer(void* arg) {

    int item;

    for(int i = 0; i < 10; i++) { // Consumes 10 items

        sem_wait(&full);  // Wait for a full slot

        pthread_mutex_lock(&mutex);  // Lock the buffer


        // Remove item from buffer

        item = buffer[out];

        printf("Consumer consumed: %d\n", item);

        out = (out + 1) % BUFFER_SIZE;  // Move index


        pthread_mutex_unlock(&mutex);  // Unlock the buffer

        sem_post(&empty);  // Increase the empty slot count


        sleep(1);  // Simulate consumption time

    }

}


int main() {

    pthread_t prodThread, consThread;


    // Initialize semaphores

    sem_init(&empty, 0, BUFFER_SIZE);

    sem_init(&full, 0, 0);

    pthread_mutex_init(&mutex, NULL);


    // Create producer and consumer threads

    pthread_create(&prodThread, NULL, producer, NULL);

    pthread_create(&consThread, NULL, consumer, NULL);


    // Wait for threads to finish

    pthread_join(prodThread, NULL);

    pthread_join(consThread, NULL);


    // Destroy semaphores and mutex

    sem_destroy(&empty);

    sem_destroy(&full);

    pthread_mutex_destroy(&mutex);


    return 0;

}








No comments:

Post a Comment

Featured Post

Data Analysis

    What is data analysis and its significance?   Data analysis is the process of collecting, transforming, and organizing data to dr...

Popular Posts