0% found this document useful (0 votes)
5 views

exp9

The document describes the implementation of the Readers-Writers Problem and the Bounded Buffer (Producer-Consumer) Problem using semaphores in C. It outlines the challenges of concurrency control, such as mutual exclusion and fair access, and provides example code for both problems. The document emphasizes the importance of semaphores in managing access to shared resources and preventing issues like buffer overflow and underflow.

Uploaded by

iyxlo126mr
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views

exp9

The document describes the implementation of the Readers-Writers Problem and the Bounded Buffer (Producer-Consumer) Problem using semaphores in C. It outlines the challenges of concurrency control, such as mutual exclusion and fair access, and provides example code for both problems. The document emphasizes the importance of semaphores in managing access to shared resources and preventing issues like buffer overflow and underflow.

Uploaded by

iyxlo126mr
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 8

Experiment-9.

AIM:

Write a program to implement Readers Writers Problem using Semaphore in C.

Theory:

The Readers-Writers Problem is a classic problem in the field of concurrency control, which deals with
managing access to shared resources by multiple processes or threads. In this specific problem, we have
two types of actors:

Readers: Processes that access and read the shared resource but don't modify it. Writers: Processes that
modify the shared resource.

The main challenge lies in ensuring mutual exclusion and fair access.

Mutual exclusion: Only one process (reader or writer) can access the shared resource at a time to avoid
data corruption. Fair access: Readers shouldn't be starved of access just because a writer is waiting.
Conversely, writers shouldn't wait indefinitely if multiple readers are present.

Here are some key points about the problem and its solutions:

Variations:

There are different variations of the Readers-Writers Problem, depending on the specific requirements and
priorities. The two most common are:

 Readers preference: Readers are given priority over writers, meaning they can access the
resource concurrently as long as no writer is waiting.

 Writers preference: Writers are given priority over readers, meaning they can access the resource
as soon as they arrive, even if readers are waiting.

Solution techniques:

The most common solution for the Readers-Writers Problem involves using semaphores. Semaphores are
synchronization objects that control access to resources by regulating the number of processes that can
access them simultaneously. Two main semaphores are used:

 Mutex: Ensures mutual exclusion. Only one process (reader or writer) can acquire the mutex to
access the critical section (shared resource).
 Write semaphore (wrt): Controls access for writers. Writers need to acquire the wrt semaphore
before accessing the critical section.
Different solutions utilize different rules for acquiring and releasing these semaphores, depending on the
chosen variation and desired fairness properties.

Example implementation:

The C program you requested demonstrates a basic implementation using readers preference. You can
analyze the code to see how semaphores are used to manage reader and writer access to the critical
section while ensuring both mutual exclusion and fair access for readers.

Further considerations:

The Readers-Writers Problem is a simplified example of a concurrency control problem. In real-world


applications, the specific requirements and complexity can be much higher. Additional considerations may
include:

 Different types of processes with varying access needs.

 Priority levels for different processes.

 Deadlock prevention mechanisms.

 Error handling and robustness.

Code:-

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

#define NUM_WRITERS 2 sem_t mutex, wrt;


int readerCount = 0;

void *reader(void *arg) {

int readerNum = *((int *)arg); while (1) {


sem_wait(&mutex); readerCount++;
if (readerCount == 1) { sem_wait(&wrt);
}

sem_post(&mutex);

printf("Reader %d is reading...\n", readerNum); sleep(1); // Simulate reading time sem_wait(&mutex);


readerCount--;

if (readerCount == 0) { sem_post(&wrt);
}

sem_post(&mutex); sleep(rand() % 5);


}

void *writer(void *arg) {

int writerNum = *((int *)arg); while (1) {


sem_wait(&wrt);

printf("Writer %d is writing...\n", writerNum); sleep(2); // Simulate writing time

sem_post(&wrt); sleep(rand() % 10);


}

int main() { sem_init(&mutex, 1, 1);


sem_init(&wrt, 1, 1);

pthread_t readerThreads[NUM_READERS], writerThreads[NUM_WRITERS]; int readerNums[NUM_READERS],


writerNums[NUM_WRITERS];
for (int i = 0; i < NUM_READERS; i++) { readerNums[i] = i;
pthread_create(&readerThreads[i], NULL, reader, &readerNums[i]);

for (int i = 0; i < NUM_WRITERS; i++) { writerNums[i] = i;


pthread_create(&writerThreads[i], NULL, writer, &writerNums[i]);

for (int i = 0; i < NUM_READERS; i++) { pthread_join(readerThreads[i], NULL);


}

for (int i = 0; i < NUM_WRITERS; i++) { pthread_join(writerThreads[i], NULL);


}

sem_destroy(&mutex); sem_destroy(&wrt); return 0;


}
Output :-

Result :-

The following program has been successfully implemented.


Experiment 9.2

Aim:-

Write a program to implement Bounded Buffer (Producer-Consumer) Problem using Semaphores in C.

Theory:-

The Bounded Buffer (Producer-Consumer) Problem is a classic example of inter-process communication and
synchronization. Two processes, the producer and the consumer, share a fixed-size buffer. The producer adds items
to the buffer, while the consumer removes items from the buffer.

Synchronization challenges:

 Mutual exclusion: Only one process (producer or consumer) can access the buffer at a time to avoid
data corruption.

 Buffer overflow: The producer shouldn't try to add an item to a full buffer.

 Buffer underflow: The consumer shouldn't try to remove an item from an empty buffer.

Solution using semaphores:

This program uses two semaphores:

 full: Counts the number of items in the buffer. The producer decrements this semaphore upon
adding an item, and the consumer increments it upon removing an item.

 empty: Counts the number of empty slots in the buffer. The producer increments this semaphore
upon adding an item, and the consumer decrements it upon removing an item.

By using these semaphores, the program ensures mutual exclusion for accessing the buffer, avoids overflow
and underflow situations, and achieves efficient communication between the producer and consumer.

Circular buffer:

This program utilizes a circular buffer to avoid buffer overflow and underflow situations. Instead of using
separate indexes for the beginning and end of the buffer, we use a single index that wraps around. This
allows us to reuse empty slots efficiently without needing to track separate ends.

Further considerations:

 This program is a basic implementation and can be enhanced with error handling, different
buffering strategies, and more complex communication protocols.
 The theory behind the Bounded Buffer problem also extends to other scenarios involving resource
sharing and synchronization in concurrent systems.

Code:-

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

#define BUFFER_SIZE 5 sem_t full, empty;


int buffer[BUFFER_SIZE]; int in = 0, out = 0;
void *producer(void *arg) {
int item;
while (1) {

item = rand() % 100; // Generate random item


sem_wait(&empty); // Wait for empty slot
buffer[in] = item;
printf("Producer produced item %d at position %d\n", item, in);
in = (in + 1) % BUFFER_SIZE; // Circular buffer
sem_post(&full); // Signal one item added
sleep(rand() % 3); // Simulate production time

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

sem_wait(&full);
printf("Consumer consumed item %d from position %d\n", item, out);
out = (out + 1) % BUFFER_SIZE;
sleep(rand() % 5); // Simulate consumption time

}
}

int main() {

sem_init(&full, 0, 0);

sem_init(&empty, 1, BUFFER_SIZE); // Initially all slots empty pthread_t producerThread,


consumerThread;
pthread_create(&producerThread, NULL, producer, NULL);
pthread_create(&consumerThread, NULL, consumer, NULL);
pthread_join(producerThread, NULL);
pthread_join(consumerThread, NULL);
sem_destroy(&full);
sem_destroy(&empty);

return 0;
}
Output :-

Result :-

The following code has been successfully implemented.

You might also like