Related Content: CS604 - VU Lectures, Handouts, PPT Slides, Assignments, Quizzes, Papers & Books of Operating Systems
There are two kinds of semaphores:
Let S be a counting semaphore. To implement it in terms of binary semaphores we need the following data structures:
Initially S1=1, S2=0, and the value of integer C is set to the initial value of the counting semaphore S. The wait operation on the counting semaphore S can be implemented as follows:
The signal operation on the counting semaphore S can be implemented as follows:
The three classic problems of synchronization are:
The bounded-buffer problem, which was introduced in a previous lecture, is commonly used to illustrate the power of synchronization primitives. The solution presented in this section assumes that the pool consists of n buffers, each capable of holding one item.
The mutex semaphore provides mutual exclusion for accesses to the buffer pool and
is initialized to the value 1. The empty and full semaphores count the number of empty
and full buffers, respectively. The semaphore empty is initialized to the value n; the
semaphore full is initialized to the value 0.
The code for the producer is as follows:
And that for the consumer is as follows:
Note the symmetry between the producer and the consumer process. This code can be interpreted as the producer producing full buffers for the consumer, or as the consumer producing empty buffers for the producer.
A data object (such as a file or a record) is to be shared among several concurrent
processes. Some of these processes, called readers, may want only to read the content of
the shared object whereas others, called writers, may want to update (that is to read and
write) the shared object. Obviously, if two readers access the data simultaneously, no
adverse effects will result. However, if a writer and some other process (whether a writer
or some readers) access the shared object simultaneously, chaos may ensue.
To ensure these difficulties do not arise, we require that the writers have exclusive
access to the shared object. This synchronization problem is referred to the readerswriters
problem. Since it was originally stated, it has been used to test nearly every new
synchronization primitive. The readers-writers problem has several variations, all
involving priorities. The simplest one, referred to as the first readers-writers problem,
requires that no reader will be kept waiting unless a writer has already obtained
permission to use the shared object. In other words, no reader should wait for other
readers to finish simply because a writer is waiting. The second readers-writers
problem requires that once a writer is ready, that writer performs its write as soon as possible. In other words, if a writer is waiting to access the object, no new readers may
start reading.
A solution to either problem may result in starvation. In the first case, writers may
starve; in the second case, readers may starve. For this reason, other variants of the
problem have been proposed. In this section, we discuss a solution to the first readerswriters
problem. In the solution to the first readers-writers problem, processes share the
following data structures.
The semaphores mutex and wrt are initialized to 1; readcount is initialized to 0. The
semaphore wrt is common to both the reader and writer processes. The mutex semaphore
is used to ensure mutual exclusion when the reader processes update the readcount
variable. The readcount variable keeps track of how many processes are currently reading
the object. The wrt semaphore is used to ensure mutual exclusion for writers or a writer
and readers. This semaphore is also used by the first and last readers to block entry of a
writer into its critical section and to allow open access to the wrt semaphore, respectively.
It is not used by readers who enter or exit, while at least one reader is in its critical
sections.
The codes for reader and writer processes are shown below:
Note that, if a writer is in the critical section and n readers are waiting, then one reader is queued on wrt, and n-1 readers are queued on mutex. Also observe that when a writer executes signal(wrt) we may resume the execution of either the waiting readers or a single waiting writer; the selection is made by the CPU scheduler.
Consider five philosophers who spend their lives thinking and eating, as shown in the following diagram.
The philosophers share a common circular table surrounded by five chairs, each belonging to one philosopher. In the center of the table is a bowl of rice, and the table is laid with five single chopsticks.
When a philosopher thinks, she does not interact with her colleagues. From time to
time, a philosopher gets hungry and tries to pick up the two chopsticks that are closest to
her (the chopsticks that are between her and her left and right neighbors). A philosopher
may pick up only one chopstick at a time. Obviously, she cannot pick up a chopstick that
is already in the hand of her neighbor. When a hungry philosopher has both her
chopsticks at the same time, she eats without releasing her chopsticks. When she is
finished eating, she puts down both of her chopsticks and starts thinking again.
The dining philosophers problem is considered to be a classic synchronization
problem because it is an example of a large class of concurrency control problems. It is a
simple representation of the need to allocate several resources among several processes in
a deadlock and starvation free manner.
One simple solution is to represent each chopstick by a semaphore. A philosopher
tires to grab the chopstick by executing a wait operation on that semaphore; she releases
her chopsticks by executing the signal operation on the appropriate semaphores. Thus the
shared data are:
All the chopsticks are initialized to 1. The structure of philosopher i is as follows:
Although this solution guarantees that no two neighbors are eating simultaneously, it
nevertheless must be rejected because it has the possibility of creating a deadlock.
Suppose that all five gets hungry at the same time and pick up their left chopsticks as
shown in the following figure. In this case, all chopsticks are locked and none of the
philosophers can successfully lock her right chopstick. As a result, we have a circular
waiting (i.e., every philosopher waits for his right chopstick that is currently being locked
by his right neighbor), and hence a deadlock occurs.
There are several possible good solutions of the problem. We will discuss these in the next lecture.