CPS 356 Lecture notes: Semaphores
Coverage: [OSCJ8] Chapter 6, §6.5 (pp. 249-255)
Introduction
Hardware solutions are complex for an application programmer to use.
To improve on this, we define a semaphore
as an abstract data type whose operations are limited to:
- initialization
- acquire(); also called wait(s) or P(s)
- release(); also called signal(s) or V(s)
definitions of acquire and release:
acquire() {
while (value <= 0);
value--;
}
release() {
value++;
}
requirements
- modifications to the semaphore value must be atomic
- testing of semaphore value in acquire must be atomic
- how can we guarantee these requirements?
Uses of semaphores
Using a binary semaphore for mutual exclusion:
Semaphore s = new Semaphore(1);
s.acquire();
// critical section
s.release();
// remainder section
Semaphores can also be used for many specific synchronization situations.
If
stmt1 in p0 must execute before stmt2
in p2, then initialize a semaphore s to 0 (see Order.java):
Semaphore s=0;
process p0 {
stmt1;
s.release();
}
process p1 {
s.acquire();
stmt2;
}
The n-process
critical section problem is solved by sharing one semaphore. If
you initialize mutex to 5, then only 5 processes could execute their
<cs> at once; it is flexible (see SemEx.java).
New defintions of acquire
and release
What is the problem with the definitions of release()
and acquire() above?
busy waiting (i.e., the waiting process uses unproductive CPU
cycles).
Spinlock: a semaphore busy waiting; it spins waiting for a
lock.
In a uniprocessor system, its waits until its time slice expires.
A modification: define a waiting list L for each semaphore.
Now we define acquire() and release() as:
acquire() {
value--;
if (value < 0) {
// add this process to list
// block;
}
}
release() {
value++;
if (value <= 0) {
// remove process p from list
// wakeup(p);
}
}
wakeup and block are basic OS system calls.
A semaphore value
can now become negative, which indicates how many processes
are waiting (e.g., if a semaphore value
is -5, then 5 processes are waiting on
that semaphore).
Semaphore a = new Semaphore(1, true); // makes the semaphore 'fair' semaphore
// which means the blocked list is a FIFO
Two ways of waiting:
- busy waiting:
process which does the busy waiting first does not
necessarily get to execute their <cs>
first
- queue:
process which goes on the blocked queue first gets to execute
their <cs> first.
Again, modifications to the semaphore value must be atomic, and
testing of semaphore value in acquire must be atomic.
How to solve this ciritical section problem?
- in a uniprocessor system
- disable interrupts, or
- use any of the techniques presented above
- hardware instructions
- Peterson's solution
- in a multiprocessor environment, use techniques above
We have simply moved busy waiting to the <cs>s
of the application programs,
and limited busy waiting to the <cs>
of the acquire() and release() operations.
Deadlock
Improper use of semaphores with wait queues can cause deadlock.
Deadlock means a group of processes are all waiting for each other
for some event.
For example (the following system has the potential for deadlock;
see Deadlock.java):
Semaphore s=1, q=1
process p0 {
s.acquire();
q.acquire();
...
s.release();
q.release();
}
process p1 {
q.acquire();
s.acquire();
...
q.release();
s.release();
}
If p0 executes S.acquire(),
then p1 executes Q.acquire(),
the processes become deadlocked.
Solution:
Semaphore s=1, q=1;
process p0 {
// order matters a great deal on the waits
q.acquire();
s.acquire();
...
// order does not matter that much on the signals
s.release();
q.release();
}
process p1 {
// order matters a great deal on the waits
q.acquire();
s.acquire();
...
// order does not matter that much on the signals
q.release();
s.release();
}
Contrast deadlock with livelock, where a thread continuously attempts
an action which fails.
Question
Why should we avoid checking the value of a semaphore?
If you check the value, would that value be meaningful?
Types of semaphores
- binary semaphore (sometimes called a mutex lock):
integer value can range only over 0 and 1
- counting semaphore:
integer value can range over an unrestricted domain
Semaphore type can be an issue of implementation, or simple how a
semaphore is used.
Binary semaphores can be simpler to implement depending on
hardware support.
Counting semaphores can be implemented using binary semaphores
Deadlock, livelock, spinlock, starvation in application programs vs. kernel
References
[OSCJ8] |
A. Silberschatz, P.B. Galvin, and G. Gagne.
Operating Systems Concepts with Java.
John Wiley and Sons, Inc., Eighth edition, 2010. |
|