Chapter 5
DEADLOCKS
Definition: A set of processes is in a deadlock state if every process in the set is waiting
for an event that can be caused by some other process in the same set.
•
•
Usually the event is release of a currently held resource
None of the processes can …
– run
– release resources
– be awakened
Processes are granted exclusive access to devices. We refer to these devices generally as
resources
Examples of computer resources
– printers
– tape drives
– files
– tables
•
•
Preemptable resources
– can be taken away from a process with no ill effects
Nonpreemptable resources
– will cause the process to fail if taken away
Example:
Assume we have one printer and one tape unit in a system, and two processes P1 and P2
running concurrently and each process should have the two resources to complete.
P1 requests the printer, gets it.
P2 requests the tape unit, gets it.
While holding the printer, P1 requests the tape unit, waits.
While holding the tape unit, P2 requests the printer, waits.
→P1 and P2 are deadlocked.
In our analysis of deadlocks, we shall make the following assumptions:
1. A process must request a resource before using it. It must release the resource after
using it. (request → use → release)
2. A process cannot request a number more than the total number of resources available
in the system.
3. For the resources of the system, a resource table shall be kept, which shows whether
each resource is free or allocated to a process. For every resource, queues shall be
kept indicating the name of processes waiting for that resource.
A deadlock occurs if and only if the following four conditions hold in a system
simultaneously:
1. Mutual Exclusion: At least one of the resources is non-sharable (i.e., only one process
can use it at a time. If another process requests that resource, the requesting process has
to wait unit the resource is released). That means each resource assigned to one process
or is available
2. Hold and wait: There must be at least one process that is holding at least one resource
and is waiting for other resources that are currently being hold by other processes. A
process holding resources can request for additional resources.
3. No preemption: No resource can be preempted before the holding process completes
its task with that resource.
4. Circular wait: There must exist a set processes {P1,P2,....,Pn} such that
P1 is waiting for the resource held by P2,
P2 is waiting for the resource held by P3,
.........
Pn-1 is waiting for the resource held by Pn,
Pn is waiting for the resource held by P1
Resource-Allocation Graph
Pi
Show processes with circles:
Rj
Show resource types with boxes:
A resource type may have more than one instance:
••
a resource of 2 instances
Rj
Pi
Request edge
Rj
Pi
Assignment edge
Assertion: A cycle in a resource-allocation graph is a necessary condition for a deadlock:
1. If the resource allocation graph contains no cycles then there is no deadlock in the
system at that instant.
2. If the resource allocation graph contains a cycle then a deadlock may exist.
3. If there is a cycle and each resource has exactly one instance then a deadlock has
occurred.
Example:
R1
•
P1
R3
•
P3
P2
••
R2
No cycles No deadlock
•••
R4
Example:
R1
•
P1
R3
•
P3
P2
Here are 2 cycles:
P1 R1 P2R3P3R2P1
P2R3P3R2P2
So, P1,P2,P3 are deadlocked
••
R2
Example:
R1
•
•
P2
P4
P1
P3
R2
••
Here is a cycle:
P1 R1 P3R2P1
But no deadlock
(P4 can finish and break the
cycle)
Modeled with directed graphs
– (a) resource R assigned to process A
– (b) process B is requesting/waiting for resource S
– (c) process C and D are in deadlock over resources T and U
An example of a circular wait:
P0
R0
R4
P4
P1
R1
R3
P3
R2
P2
Processes {P0, P1..Pn} are involved in circular wait iff Pi is waiting for Ri which is held
by Pi+1 and Pn is waiting for Rn held which is held by P0 (circular waiting)
Methods Of Handling Deadlocks:
1. Deadlock prevention
2. Deadlock avoidance
3. Deadlock detection
4. Recovery from deadlock
5. Ignore deadlocks (UNIX)
1. Deadlock prevention
Ensure that at least one of the four conditions we discussed before cannot hold.
Mutual exclusion:
In general we don’t have systems with all resources being sharable. Some resources like
printers, processing units are non-sharable. So, it is not possible to prevent deadlocks by
denying mutual exclusion.
Hold-and-wait:
* One protocol to ensure that hold-and-wait condition never occurs is: “each process
must request and get all of its resources before it begins execution.”
• Problems
– may not know required resources at start of run
– also ties up resources other processes could be using
* Another protocol is: “each process can request resources only when it has no
resources allocated.”
The second protocol is better. However, both protocols cause low resource utilization and
starvation. Many resources are allocated but most of them are unused for a long period of
time. A process that requests several commonly used resources may have to wait
indefinitely.
No preemption:
* One protocol is: “if a process that is holding some resources requests another resource
and that resource cannot be allocated to it, then it must release all resources that are
currently allocated to it.”
* Another protocol is: “when a process requests some resources, if they are available,
allocate them. If a resource it requested is not available, then it checks whether this
resource is being used or it is allocated to some other resources waiting for other
resources. If that resource is not being used, then preempt it from the waiting process and
allocate it to the requesting process. If that resource is being used, the requesting process
must wait.”
•
•
This is not a viable option
Consider a process given the printer
– halfway through its job
– now forcibly take away printer …….?????
Instead revise the last two sentences above with the following:
“…If that resource has not been used, then preempt it from the waiting process and
allocate it to the requesting process. If that resource has been used, the requesting process
must wait.”
Circular wait:
* One protocol to ensure that the circular wait condition never holds is: “Impose a
linear ordering of all resource types. Then, each process can only request resources in an
increasing order of enumeration.”
How to go about proving this:
Formally define a function.
F: R→N
Where R= {R1, R2, …. , Rn} is a set of resource types, and N is the set of natural
numbers.
For example:
F (tape driver) = 1
F (disk driver) = 5
F (printer) = 12
etc.
So, if a process wants to use the tape drive and the printer, it should first request the tape
drive, then the printer.
Whenever a process requests a resource Ri, it must have released all resources Rj with:
F (Rj) ≥ F (Ri).
With the above protocol, a circular wait is impossible.
Proof: (by contradiction)
Assume a set of processes is in a circular wait: {P1, P2, …. , Pn}
Every Pi+1 is holding Ri and requesting Ri+1. So, we must have
F (Rj) < F (Ri+1), i = 1,2, .....
That means:
F (R1) < F (R2) < … < F (Rn) < F (R1)
F (R1) < F (R1)!!??
2. Deadlock Avoidance:
Given some additional information on how each process will request resources, it is
possible to construct an algorithm that will avoid deadlock states. The algorithm will
dynamically examine the resource allocation operations to ensure that there won’t be a
circular wait on resources.
When a process requests a resource that is already available, the resource is
immediately allocated only if it leaves the system in a safe state.
A state is safe if the system can allocate resources to each process in some order (safe
sequence of processes) avoiding a deadlock. A deadlock state is an unsafe state.
Example:
Consider a system with 12 tape drives and 3 processes P0, P1 and P2. Assume that we
know the maximum number of tape drives each processes may request as: P0 requires 10
tape drives, P1 requires 4, and P2 requires as many as 9.
Suppose at time t0, 9 tape drives are allocated as follows: P0←5, P1←2, and P2←2. So,
we have:
Process
Current needs
Deficit
Maximum needs
Available
P0
P1
P2
(currently being used)
(more needed in the
future)
5
2
2
5
2
7
10
4
9
3
3
3
→ at this time there are 12-(5+2+2)=3 free tape drives. The sequence <P1, P0, P2> is a
safe sequence.
Note: It is possible to go from a safe to an unsafe state:
Consider the above example. Assume at time t1, P2 requests one tape drive and gets it.
→ the system is in an unsafe state, because only P1 can be allocated all its tape drive,
finishes and returns all 4 tape drives, but
P0 is allocated 5, may request 5 more → has to wait
P2 is allocated 3, may request 6 more → has to wait
P0 and P2 may be deadlocked!
Banker’s Algorithm: [a deadlock avoidance algorithm]
Let m be the number of the resource types, and n be the number of processes. The
following data structures are used in the algorithm:
Available [m]: A vector of length m indicates the number of available resources of each
type. If Available [i] = k, there are k instances of resource type Rj available.
Max [n,m]: Two dimensional array of size n × m. It defines the maximum total demand
of each process from each resource type. For example, if Max [i,j] = k, then Pi may
request at most k instances of resource type Rj ever.
Allocation [n,m]: Two dimensional array of size n × m. It defines the number of
resources of each type currently allocated to each process. For example, if Allocation [i,j]
= k, then Pi is currently allocated k instances of resource type Rj.
Need [n,m]: Two dimensional array of size n × m, It indicates the remaining resource
need of each process. For example, if Need [i,j] = k, then Pi may need k more instances
of resource type Rj to complete.
Note that Need [i,j] = Max [i,j] – Allocation [i,j] for all i= 1..n & j= 1..m
Now, take each row vector in Allocation and Need as Allocation (i) and Need (i). So,
Allocation (i) specifies the resources currently allocated to process Pi.
Let X and Y be vectors of length n. We say:
X≤Y
X[i] ≤ Y[i], i=1, 2, …, n
X<Y
X ≤ Y and X ≠ Y
The Algorithm
1. Process Pi makes request for resources. Let the Request (i) be the corresponding request
vector.
2. If Request(i) > Need(i), then there is an error
3. Otherwise, if Request(i)> Available, then Pi must wait.
4. Otherwise, modify the data structures as follows:
Available ═ Available – Request(i)
Allocation(i )═ Allocation(i) + Request(i)
Need(i) ═ Need(i) - Request(i)
5. Check whether the resulting state is safe (Use the safety algorithm presented below)
6. If the state is safe, do the allocation. Otherwise Pi must wait for Request.
Safety Algorithm to perform step 5 in Banker’s Algorithm
Let Work and Finish be vectors of length m and n respectively.
A1: Initialize Work ═ Available, Finish[i] ═ false, for all i.
A2: Find an i such that
a)
Finish [i] ═ false and
b)
Need (i) ≤ Work
If no such i is found, then go to step A4.
A3: If an i is found, then for that i do:
Work ═ Work + Allocation (i)
Finish [i] ═ true
Go to step A2
A4: If Finish [i] ═ true for all i, then the system is in a safe state
Example:
Suppose a system with three resource types is supporting two processes. The state of the
system is as follows.
Available ═ [1 4 1]
P1
P2
MAX
R1 R2 R3
1
3
1
1
4
1
ALLOCATION
R1
R2
R3
0
0
0
0
0
0
Suppose Request (1) is to be processed:
Available ═ [ 1 4 1] - [ 1 2 0] ═ [ 0 2 1].
Allocation ═ 1 2 0
00 0
Need
═
0 1 1
1 4 1
Now apply the safety algo.
Work
═ [ 0 2 1]
Finish
═ false
false
i═1 : Need (1) ═ [ 0 1 1 ] ≤ Work? Yes
Work ═ Work + Allocation (1) ═ [ 1 4 1]
Finish [1] ═ true
i═2 : Need (2) ═ [ 0 4 1 ] ≤ Work? Yes
REQUEST
R1
R2
R3
1
2
0
0
2
1
NEED
R1 R2 R3
1
3
1
1
4
1
Work ═ Work + Allocation (2) ═ [ 1 4 1]
Finish [2] ═ true
═> System is in safe state, so do the allocation.
Exercise: Repeat the previous example for the Request (2), and check if the system will
end up in an unsafe state or not.
3. Deadlock Detection:
If a system has no deadlock prevention and no deadlock avoidance scheme, then it
needs a deadlock detection scheme with recovery from deadlock capability. For this,
information should be kept on the allocation of resources to processes, and on
outstanding allocation request. Then, an algorithm is needed which will determine
whether the system has entered a deadlock state. This algorithm must be invoked
periodically.
Deadlock Detection Algorithm (Shoshani and Coffman)
Data structures used:
* Available[m]: as in Banker’s Algorithm
* Allocation [n, m]: as in Banker’s Algorithm
* Request [n,m]: A two dimensional array of size n×m which indicates the current
request of each process. If Request [i,j] ═ k, then Pi, is requesting k more instances of
resource type Rj, Allocation(i), Request(i) are the i’th rows of Allocation and Request
matrices.
* Work and Finish are vectors of length m and n, as in the safety algorithm.
The Algorithm:
A1: Initialize Work ═ Available
For i ═ 1 to n do
If Allocation (i ) ═ 0 then Finish[i] ═ true
else Finish[i] ═ false
A2: Find an i such that
a) Finish[i] ═ false
b) Request (i) ≤ Work
If no such i can be found, go to A4
A3: For that i found in A2 do
Work ═ Work + Allocation (i)
Finish[i] ═ true
go to A2
A4: If Finish [i] ≠ true for all i,
then the system is in a deadlock state and for those i’s for which Finish[i] ═ false,
Pi’s are deadlocked.
Example:
Suppose that at time To we have the following resources allocation state:
P1
P2
P3
P4
P5
Allocation
R1
R2
0
1
2
0
3
0
2
1
0
0
R3
0
2
3
1
2
Request
R1 R2 R3
0
0
0
2
0
2
0
0
0
1
0
0
0
0
2
Available
R1 R2
R3
0
0
0
The sequence <P1, P3, P4, P2, P5> will not lead the system into a deadlock state! We have
found one solution; the system will be safe after allocation.
Let’s apply the detection algorithm:
A1: Work = [0 0 0]
Finish [i] = False, i = 1 … 5
A2: P1 : Finish [1] = False, Request [1] ≤ Work (i.e [0 0 0] ≤ [0 0 0])
A3: Work = [0 0 0] + [0 1 0] = [0 1 0]
Finish [1] = True
A2: P3 : Finish [3] = False, Request [3] ≤ Work (i.e [0 0 0] ≤ [0 1 0])
A3: Work = [0 1 0] + [3 0 3] = [3 1 3]
Finish [3] = True
A2: P4 : Finish [4] = False, Request [4] ≤ Work (i.e [1 0 0] ≤ [3 1 3])
A3: Work = [3 1 3] + [2 1 1] = [5 2 4]
Finish [4] = True
A2: P2 : Finish [2] = False, Request [2] ≤ Work (i.e [2 0 2] ≤ [5 2 4])
A3: Work = [5 2 4] + [2 0 2] = [7 2 6]
Finish [2] = True
A2: P5: Finish [5] = False, Request [5] ≤ Work (i.e [0 0 2] ≤ [7 2 6])
A3: Work = [7 2 6] + [0 0 2] = [7 2 8]
Finish [5] = True
A4: Finish [i] = True for all i → no deadlock at this moment
Exercise: Suppose now that P3 makes one additional request for an instance of type R3.
So, the Request matrix is modified as follows:
P1
P2
P3
P4
P5
Request
R1 R2 R3
0 0 0
2 0 2
0 0 1
1 0 0
0 0 2
Apply the algorithm and prove that a deadlock exists, consisting of P2, P3, P4, and P5.
4. Recovery from Deadlock:
If the system is in a deadlock state, some method for recovering it from the deadlock
must be applied. There are various ways of recovery from deadlock:
1. Allocate one resource to several processes, by violating mutual exclusion.
2. Preempt some resources from some of the deadlocked processes.
3. Abort one or more processes in order to break the deadlock (mostly this is done)
If preemption is used:
1. Select a victim. (Which resources are to be preempted from which processes?)
2. Rollback. If we preempt a resource from a process, roll the process back to some safe
state and restart it (how to determine that safe state???!)
Problem: Starvation. How can we guarantee that resources will not always be preempted
from the same process?
In selecting a victim, important parameters are:
Process priorities
How long the process has computed?
How long does it need to finish?
How many resources of what type did the process use?
How many more resources does the process need to finish?
How many processes will be rolled back? (we may select more than one victim)
Note: To avoid starvation, ensure that a process can be selected as a victim only a small
number of times. So, it is wise idea to include the number of rollbacks as a parameter.
5. Ignore Deadlock: (UNIX)
UNIX does not provide any method to handle deadlocks. For example, the total number
of processes of UNIX is limited by the size of process table. So, process table slots are
finite resources. If a system call FORK fails because the table is full, the possible
approach for the program (doing FORK) is to wait a random time and try again.
Assume a UNIX system has 100 process slots. 10 processes are running, each of which
needs to create a 12 (sub) processes. After each process has created 9 subprocesses → 10
original + 90 new processes has exhausted the table→ each of the original processes now
sits in an endless loop forking and failing→ deadlock!. The probability of this happening
is minuscule, but it could happen.
So, the UNIX approach is just to ignore the problem on the assumption that most users
would prefer an occasional deadlock to a rule restricting all users to one process, one
open file, and one of everything.
© Copyright 2026 Paperzz