Deadlocks and dining Philosophers
The dining philosophers problem, attributed to
Dijkstra, describes a situation
in which five philosophers sit around a table. There are five plates, five forks
(between the plates) and a bowl of spaghetti in the middle of the table. (Some
versions use rice and chopsticks but Dijkstra apparently preferred pasta.) Each
philosopher needs two forks to eat. How can all of the philosophers eat from time
to time without reaching deadlock and starving?
There are many solutions to this problem; part of the difficulty is that there is
no one solution. The problem has become a standard way of describing the
difficulties that arise when multiple processes compete for a finite number of
resources.
One simple solution is to make sure there are only four philosophers at
the table; this ensures that at least one will find two forks. Another is to
arrange that one of them pick up the left rather than the right fork first.
More complicated solutions involve the use of semaphores or messages.
For deadlock to occur, four conditions must be true.
- Mutual Exclusion
There must be mutual exclusion among the processes. That is,
at least one resource must not be shareable.
- Hold and Wait At least one process must be holding
a resource and waiting to acquire a resource currently held by
another process.
- No Preemption Resources cannot be taken away from
a process; it must release them as a normal event.
- Circular Wait A process holding one resource (A)
and waiting for another (B) must be matched by another process that
needs A and holds B (there can be more than one such process;
perhaps one process needs A and holds C, another needs C and holds B.)
When these four conditions hold, deadlock is possible. If each
philosopher takes one fork, deadlock ensues; no one can eat until
at least one philosopher puts down at least one fork.
There are three general approaches to solving the problem of deadlock:
- Prevention One of the four necessary conditions for
deadlock may be prevented from occurring. A printer, for example,
is not a shareable resource; whatever process is using it must have
exclusive use. Other resources may be shareable (read-only files,
for instance) and for these the prevention of mutual exclusion would
be possible. If all the resources required by a process are known in
advance, they can be
allocated as a group; then hold-and-wait is not possible. For cpu time,
preemption is possible; the state of the preceding process is put on the
stack so it is recoverable. Finally, circular wait may be avoided by
ranking resources and allowing processes to acquire only resources with a
higher rank.
- Avoidance To avoid deadlock, it is necessary to know
what resources processes will need; then, when a new request is made,
it is possible to see if granting it will result in a situation in
which deadlock can occur.
Dijkstra's banking algorithm is one way to achieve this result.
- Detection and Recovery If neither of the previous
strategies is used, it is necessary to detect deadlock when it
occurs and impose some solution; generally to kill some or all of the
processes, or to preempt one or more of them. This is rather a
brute force approach; if
processes need mutual exclusion, for instance, it is for a reason, and
simply terminating a process in the middle of writing to a file will result
in loss of data.
Which of these methods should we use? All of them. Clearly there
are times at which any may be the preferred solution. A systematic
way to decide, suggested by Peterson and Silberschatz, is as follows.
Divide resources into the following groups, in order of priority:
- Internal Resources Resources used by the operating system, for
example Process Control Blocks.
- Main Memory RAM
- Job Resources I/O Devices and files; assignable resources.
- Swap Space Hard drive space used by each process to save its state.
Then the following approaches make sense.
- Resource ordering - a preventive technique - can be used to allocate
internal resources, because these resources are not used by processes.
- Since the contents of RAM can be written to disk to allow memory
swapping, preemption is possible here; the preempted process can
always regain the information from the hard drive.
- The resources such as I/O devices needed by a process can usually be
known in advance; thus avoidance is a good strategy to avoid
deadlock.
- Prevention can be achieved by allocating all the space needed at once.
This is usually true for storage space requirements.