السادسة
السادسة
References:
1. Abraham Silberschatz, Greg Gagne, and Peter Baer Galvin, "Operating
System Concepts, Ninth Edition ", Chapter 5
Warning: This chapter requires some heavy thought. As you read each of the
algorithms below, you need to satisfy yourself that they do indeed work under
all conditions. Think about it, and don't just accept them at face value.
5.1 Background
Recall that back in Chapter 3 we looked at cooperating processes ( those
that can effect or be effected by other simultaneously running
processes ), and as an example, we used the producer-consumer
cooperating processes:
Producer code from chapter 3:
item nextProduced;
while( true ) {
/* Produce an item and store it in nextProduced
*/
nextProduced = makeNewItem( . . . );
S1;
signal( synch );
and in process P2 we insert the code:
wait( synch );
S2;
Because synch was initialized to 0, process P2 will block
on the wait until after P1 executes the call to signal.
5.6.2 Semaphore Implementation
The big problem with semaphores as described above is the busy loop in
the wait call, which consumes CPU cycles without doing any useful
work. This type of lock is known as a spinlock, because the lock just sits
there and spins while it waits. While this is generally a bad thing, it does
have the advantage of not invoking context switches, and so it is
sometimes used in multi-processing systems when the wait time is
expected to be short - One thread spins on one processor while another
completes their critical section on another processor.
An alternative approach is to block a process when it is forced to wait for
an available semaphore, and swap it out of the CPU. In this
implementation each semaphore needs to maintain a list of processes that
are blocked waiting for it, so that one of the processes can be woken up
and swapped back in when the semaphore becomes available. ( Whether
it gets swapped back into the CPU immediately or whether it needs to
hang out in the ready queue for a while is a scheduling problem. )
The new definition of a semaphore and the corresponding wait and
signal operations are shown as follows:
Note that in this implementation the value of the semaphore can actually
become negative, in which case its magnitude is the number of processes
waiting for that semaphore. This is a result of decrementing the counter
before checking its value.
Key to the success of semaphores is that the wait and signal operations
be atomic, that is no other process can execute a wait or signal on the
same semaphore at the same time. ( Other processes could be allowed to
do other things, including working with other semaphores, they just can't
have access to this semaphore. ) On single processors this can be
implemented by disabling interrupts during the execution of wait and
signal; Multiprocessor systems have to use more complex methods,
including the use of spinlocking.
5.6.3 Deadlocks and Starvation
One important problem that can arise when using semaphores to block
processes waiting for a limited resource is the problem of deadlocks,
which occur when multiple processes are blocked, each waiting for a
resource that can only be freed by one of the other ( blocked ) processes,
as illustrated in the following example. ( Deadlocks are covered more
completely in chapter 7. )