Thanks to visit codestin.com
Credit goes to www.scribd.com

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

OS Lab Mutex Semaphore With Process No Sol

The document covers concepts related to critical sections, mutexes, and semaphores in operating systems. It includes tasks for observing race conditions, implementing mutexes and semaphores for synchronization, and using named semaphores for process synchronization with shared memory. Additionally, it poses reflection questions to compare synchronization primitives and their appropriate use cases.

Uploaded by

abdulhady378
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)
5 views5 pages

OS Lab Mutex Semaphore With Process No Sol

The document covers concepts related to critical sections, mutexes, and semaphores in operating systems. It includes tasks for observing race conditions, implementing mutexes and semaphores for synchronization, and using named semaphores for process synchronization with shared memory. Additionally, it poses reflection questions to compare synchronization primitives and their appropriate use cases.

Uploaded by

abdulhady378
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

Operating Systems Lab: Critical Section,

Mutexes, and Semaphores


Learning Outcomes
- Understand the concept of a critical section.
- Explore race conditions through a simple example.
- Apply mutexes and semaphores to synchronize access.
- Compare different synchronization primitives.

Part 1: Illustrative Task — Race Condition and Mutex


Task: Observe a Race Condition and Solve it with a Mutex

Instructions:
1. Write a program that creates two threads.
2. Each thread increments a shared global counter 1,000,000 times.
3. First, run the code without any synchronization.
4. Then, add a pthread_mutex_t to protect the increment operation.

Starter Code (Without Mutex):

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

long counter = 0;

void* increment(void* arg) {


for (long i = 0; i < 1000000; i++) {
counter++;
}
return NULL;
}

int main() {
pthread_t t1, t2;
pthread_create(&t1, NULL, increment, NULL);
pthread_create(&t2, NULL, increment, NULL);

pthread_join(t1, NULL);
pthread_join(t2, NULL);

printf("Final counter value: %ld\n", counter);


return 0;
}

Functions to be used
pthread_mutex_t lock;

pthread_mutex_init(&lock, NULL);
pthread_mutex_lock(&lock);

pthread_mutex_unlock(&lock);

pthread_mutex_destroy(&lock);

Modified Code (With Mutex):

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

long counter = 0;

void* increment(void* arg) {


for (long i = 0; i < 1000000; i++) {
counter++;
}
return NULL;
}

int main() {
pthread_t t1, t2;
pthread_create(&t1, NULL, increment, NULL);
pthread_create(&t2, NULL, increment, NULL);

pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("Final counter value: %ld\n", counter);
return 0;
}
Part 2: Challenge Task — Binary Semaphore for Synchronization
Task: update the following code to use binary semaphore

Instructions:
1. Modify your mutex-based code to use POSIX unnamed semaphores (sem_t).
2. Initialize a semaphore to 1 (binary semaphore).
3. Use sem_wait() before and sem_post() after the increment operation.
4. Verify that synchronization still works using semaphore instead of mutex.

Functions to be used

sem_t sem;

sem_init(&sem, 0, 1);

sem_wait(&sem);

sem_post(&sem);

Code Using Semaphore:

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

long counter = 0;

void* increment(void* arg) {


for (long i = 0; i < 1000000; i++) {

counter++;

}
return NULL;
}

int main() {
pthread_t t1, t2;
pthread_create(&t1, NULL, increment, NULL);
pthread_create(&t2, NULL, increment, NULL);

pthread_join(t1, NULL);
pthread_join(t2, NULL);
sem_destroy(&sem);
printf("Final counter value: %ld\n", counter);
return 0;
}

Reflection Questions
1. What is the difference between a mutex and a binary semaphore?
2. Which synchronization primitive is more appropriate for mutual exclusion and why?
3. Can you identify scenarios where a counting semaphore is more useful than a mutex?

Part 3: Additional Task — Process Synchronization Using Semaphore


Task: Use Named Semaphore for Synchronization Between Processes

Instructions:
1. Create a program that forks into two processes.
2. Each process should increment a shared memory counter 1,000 times.
3. Use a POSIX named semaphore (`sem_open`, `sem_wait`, `sem_post`) to protect access to
the shared counter.
4. Use `mmap` or `shm_open` to create shared memory for the counter.
5. After both processes finish, print the final value.

Functions to be used:
sem_t *sem = sem_open("/mysem", O_CREAT, 0644, 1);
sem_wait(sem);

sem_post(sem);

sem_close(sem);
sem_unlink("/mysem");

Example Code (Process-based with Named Semaphore):

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/wait.h>

int main() {
int *counter = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
*counter = 0;
pid_t pid = fork();
if (pid == 0) { // Child process
for (int i = 0; i < 1000; i++) {

(*counter)++;

}
exit(0);
} else {
for (int i = 0; i < 1000; i++) {
(*counter)++;
}
wait(NULL);
printf("Final counter value: %d\n", *counter);
munmap(counter, sizeof(int));
}
return 0;
}

You might also like