Operating Systems Lab Assignment 6: Synchronization Using Semaphores
Operating Systems Lab Assignment 6: Synchronization Using Semaphores
Objectives
1. To use semaphores for synchronization
2. To develop a C program to solve the producer – consumer problem
Guidelines
You have learned in class that threads run concurrently and when they read/write to a shared memory, the
program behavior is undefined. This is due to the fact the CPU scheduler switches rapidly between threads to
provide concurrent execution. One thread may only partially complete execution before another thread is
scheduled. Therefore, a thread may be interrupted at any point in its instruction stream, and the CPU may be
assigned to execute instructions of another thread, and so the thread schedule is non-deterministic and the
resulting output is non-reproducible. To control the non-deterministic and non-reproducible behavior of multi-
threaded programs, synchronization is required.
Each thread has a segment of code that involves data sharing with one or more threads. This code segment is
referred to as a critical section. Synchronization imposes a rule that when one thread is executing in its critical
section, no other thread is allowed to execute in its critical section. Each thread must request permission to enter
its critical section, formally defined as the entry section. When a thread completes execution in the critical section,
it leaves through an exit section to the remaining code of the program. The general structure of synchronization is
therefore defined as follows:
do {
entry section
critical section
exit section
remainder section
} while (1);
A variety of synchronization tools exit. In this lab, semaphores are used for demonstration. A semaphore
is considered a generalized lock and it supports two operations:
- P(): an atomic operation that waits for semaphore to become positive, then decrements it by 1. This
operation is referred to as wait() operation
- V(): an atomic operation that increments the semaphore by 1, waking up a waiting P, if any. This
operation is referred to as signal() operation.
P() stands for “proberen” (to test) and V() stands for “verhogen” (to increment) in Dutch. Linux provides a high-
level APIs for semaphores in the <semaphore.h> library:
sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_wait(sem_t *sem);
int sem_post(sem_t *sem);
Step 1. Download the threadSync.c program from iLearn, then compile and run several times. The comment at
the top of program explains how to compile and run the program.
*program to write: produce -consumer problem to produce and consume the alphabet.
//Producer thread
do {
…
produce next item
…
wait(empty);
wait(mutex);
…
add the item to buffer
…
signal(mutex);
signal(full);
} while (1);
//Consumer thread
do {
wait(full)
wait(mutex);
…
remove next item from buffer
…
signal(mutex);
signal(empty);
…
consume the item
…
Be sure to retain copies of your .c and .txt files. You will want these for study purposes and to resolve any grading
questions (should they arise)
Please start each program/ text with a descriptive block that includes minimally the following information: