0% found this document useful (0 votes)
33 views5 pages

LCB2022057 DivyanshGautam assignmentOS

The document discusses two questions related to thread synchronization. The first question involves modifying a program with two processes to add synchronization using a semaphore for iteration control and critical sections. The second question involves writing a C/Java program demonstrating producer-consumer problem synchronization using counting semaphores and a mutex.

Uploaded by

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

LCB2022057 DivyanshGautam assignmentOS

The document discusses two questions related to thread synchronization. The first question involves modifying a program with two processes to add synchronization using a semaphore for iteration control and critical sections. The second question involves writing a C/Java program demonstrating producer-consumer problem synchronization using counting semaphores and a mutex.

Uploaded by

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

ASSIGNMENT - OS

Q. 1 Two processes, Process A and Process B, are accessing a shared variable counter. You want to ensure data
consistency by synchronising their access.
Part 1: Semaphores for Iteration Control
You are given a program with two processes (A and B) that iterate and print values. Modify the program to implement
synchronization using a semaphore.
Process A should not start iteration i before Process B finishes iteration i-1.
Explain the changes you made and how they achieve synchronization.
Part 2: Semaphores for Critical Sections
Modify the program again to simulate a scenario where both processes modify the shared variable counter.
Identify the critical section for each process (the code segment that modifies the counter).
Use a semaphore to ensure mutual exclusion between the two processes when accessing their critical sections.
Explain the placement of the semaphore operations (wait and signal) within the code to achieve synchronization.

Q.2 Write a C or JAVA program for thread synchronisation using counting semaphores. Application to
demonstrate:producer-consumer problem with counting semaphores and mutex.

LCB2022057
DIVYANSH GAUTAM
#include <iostream> // Process B function
#include <thread> void process_b() {
Q1: #include <mutex> for (int i = 0; i < MAX_ITERATIONS; ++i) {
#include <semaphore.h> // Wait for Process A to finish iteration i
sem_wait(&iteration_semaphore);
// Define the maximum number of
iterations // Critical section for Process B
#define MAX_ITERATIONS 5 std::lock_guard<std::mutex> lock(counter_mutex);
counter--; // Decrement the counter
// Shared variables std::cout << "Process B - Counter: " << counter << std::endl;
int counter = 0;
sem_t iteration_semaphore; // Semaphore // Signal Process A to start its next iteration
for iteration control sem_post(&iteration_semaphore);
sem_t critical_section_semaphore; // }
Semaphore for critical sections }
std::mutex counter_mutex; // Mutex for
mutual exclusion int main() {
// Initialize semaphores
// Process A function sem_init(&iteration_semaphore, 0, 1); // Initialize with value 1
void process_a() { sem_init(&critical_section_semaphore, 0, 1); // Initialize with value 1
for (int i = 0; i < MAX_ITERATIONS; ++i) {
// Wait for Process B to finish iteration // Create threads for Process A and Process B
i-1 std::thread thread_a(process_a);
sem_wait(&iteration_semaphore); std::thread thread_b(process_b);

// Critical section for Process A // Join threads


std::lock_guard<std::mutex> thread_a.join();
lock(counter_mutex); thread_b.join();
counter++; // Increment the counter
std::cout << "Process A - Counter: " << // Destroy semaphores
counter << std::endl; sem_destroy(&iteration_semaphore);
sem_destroy(&critical_section_semaphore);
// Signal Process B to start its next
iteration return 0;
sem_post(&iteration_semaphore); }
}
}
EXPLANATION:
1. Iteration Control using Semaphores:
The iteration_semaphore semaphore is initialized with a value of 1, ensuring mutual exclusion
for the iteration control.
Before each process starts its iteration, it waits for the other process to finish its iteration by
calling sem_wait(&iteration_semaphore).
After finishing its iteration, each process signals the other process to start its next iteration by
calling sem_post(&iteration_semaphore).
2. Critical Sections using Mutex and Semaphores:
Each process has its critical section, where it accesses the shared variable counter.
A mutex (counter_mutex) is used to ensure mutual exclusion within the critical sections,
preventing data race conditions.
Before entering the critical section, each process waits for the semaphore iteration_semaphore,
ensuring that Process A does not start iteration i before Process B finishes iteration i-1.
After leaving the critical section, each process signals the semaphore iteration_semaphore,
allowing the other process to enter its critical section.
Q2: #include <stdio.h>
void* consumer(void* arg) {
while (1) {
#include <pthread.h> sem_wait(&full); // Wait for a filled slot in the buffer
pthread_mutex_lock(&mutex); // Lock the mutex
#include <semaphore.h>
// Critical section
int item = buffer[index_consumer];
#define BUFFER_SIZE 5 // Size of the buffer printf("Consumed: %d\n", item);
index_consumer = (index_consumer + 1) % BUFFER_SIZE;
sem_t empty; // Semaphore to track empty slots in the buffer pthread_mutex_unlock(&mutex); // Unlock the mutex
sem_t full; // Semaphore to track filled slots in the buffer sem_post(&empty); // Signal that a slot in the buffer is empty
pthread_mutex_t mutex; // Mutex for mutual exclusion }
int buffer[BUFFER_SIZE]; // Shared buffer return NULL;
int index_producer = 0; // Index for the producer }
int index_consumer = 0; // Index for the consumer
int main() {
pthread_t producer_thread, consumer_thread;
void* producer(void* arg) {
int item = 1; // Initialize semaphores and mutex
while (1) { sem_init(&empty, 0, BUFFER_SIZE);
sem_wait(&empty); // Wait for an empty slot in the buffer sem_init(&full, 0, 0);
pthread_mutex_lock(&mutex); // Lock the mutex pthread_mutex_init(&mutex, NULL);
// Critical section
buffer[index_producer] = item; // Create producer and consumer threads
pthread_create(&producer_thread, NULL, producer, NULL);
printf("Produced: %d\n", item);
pthread_create(&consumer_thread, NULL, consumer, NULL);
item++;
index_producer = (index_producer + 1) % BUFFER_SIZE; // Join threads
pthread_mutex_unlock(&mutex); // Unlock the mutex pthread_join(producer_thread, NULL);
sem_post(&full); // Signal that a slot in the buffer is filled pthread_join(consumer_thread, NULL);
}
return NULL; // Destroy semaphores and mutex
} sem_destroy(&empty);
sem_destroy(&full);
pthread_mutex_destroy(&mutex);

return 0;
}
In this program:
We have two threads: producer and consumer.
The producer produces items and puts them into a shared buffer.
The consumer consumes items from the buffer.
We use two semaphores (empty and full) to keep track of empty and filled slots
in the buffer, respectively.
We use a mutex (mutex) to ensure mutual exclusion when accessing the shared
buffer.
The producer waits for an empty slot in the buffer before producing an item and
signals that a slot in the buffer is filled after producing an item.
The consumer waits for a filled slot in the buffer before consuming an item and
signals that a slot in the buffer is empty after consuming an item.
This ensures that the producer and consumer synchronize their operations
properly, preventing issues such as buffer overflow or underflow.

You might also like