LAB 5 - Semaphore Implementation
LAB 5 - Semaphore Implementation
1. What is a Semaphore?
A semaphore is a variable or abstract data type that is used for controlling access to a shared
resource by multiple processes or threads in a concurrent system. It maintains a count of the
available resources and provides operations to wait for a resource to become available (down
operation) and signal that a resource has been released (up operation).
2. Semaphore Operations:
Wait (down) operation (sem_wait): Decrements the semaphore count by one. If the
count becomes negative, the calling thread or process is blocked until the count becomes
positive again.
Signal (up) operation (sem_post): Increments the semaphore count by one, waking up
any threads or processes that are waiting for the semaphore.
3. Implementation of Semaphore:
In C, semaphores are typically implemented using the POSIX semaphore API, which
provides functions for initializing, waiting on, and signaling semaphores. Here's a basic
implementation of a semaphore using POSIX threads and functions:
This code demonstrates a simple example of using semaphores for thread synchronization
in a concurrent program.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h> // For sleep function
#define NUM_THREADS 5
// Global semaphore
sem_t semaphore;
// Thread function
void *thread_func(void *arg) {
int tid = *(int *)arg; // Thread ID
// Print a message indicating the thread has entered the critical section
printf("Thread %d has entered the critical section.\n", tid);
// Signal semaphore
sem_post(&semaphore);
pthread_exit(NULL);
}
int main() {
pthread_t threads[NUM_THREADS]; // Array to store thread IDs
int thread_ids[NUM_THREADS]; // Array to store thread IDs
// Initialize semaphore
if (sem_init(&semaphore, 0, 1) != 0) { // Initialize the semaphore with a value of 1
perror("Semaphore initialization failed");
exit(EXIT_FAILURE);
}
// Create threads
for (int i = 0; i < NUM_THREADS; i++) {
thread_ids[i] = i; // Assigning thread ID
if (pthread_create(&threads[i], NULL, thread_func, &thread_ids[i]) != 0) { // Create
threads
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
}
// Join threads
for (int i = 0; i < NUM_THREADS; i++) {
if (pthread_join(threads[i], NULL) != 0) { // Wait for threads to finish
perror("Thread join failed");
exit(EXIT_FAILURE);
}
}
// Destroy semaphore
sem_destroy(&semaphore);
return 0;
}
Step 2: Save the Code
Save the code above into a file named semaphore.c.
Step 3: Compile the Code
In the Cygwin terminal, navigate to the directory where you saved semaphore.c and run the
following command to compile it:
gcc -o semaphore semaphore.c -pthread
Step 4: Run the Executable
After successful compilation, you will find an executable named semaphore in the same
directory. Run it using the following command:
./semaphore
Step 5: Verify Output
You should see output from each thread as they enter and exit the critical section, controlled
by the semaphore.
4. Explanation of Code: