Introduction

Prevention makes deadlock impossible by restricting how processes request resources. Avoidance is gentler: processes request resources freely, but each process declares in advance the maximum it may ever need, and the OS grants a request only if the system stays in a safe state, one from which every process can still finish. Dijkstra's Banker's algorithm is the classic avoidance method; the name comes from a banker who never lends so much that he could not satisfy all his customers' credit limits in some order.

The price is advance knowledge of maximum claims, a fixed number of processes and resources, and an O(mn2)O(m n^2) check on every request. The benefit is that resources are not wasted the way they are under hold-and-wait prevention.

Prerequisites

Core concepts

Data structures

For nn processes and mm resource types:

NameShapeMeaning
Availablevector of mmFree instances of each type
Maxn×mn \times mMaximum demand of each process
Allocationn×mn \times mInstances currently held
Needn×mn \times mMax−Allocation\text{Max} - \text{Allocation}: what each process may still request

Vectors are compared component-wise: X≤YX \le Y means X[j]≤Y[j]X[j] \le Y[j] for every jj.

Safe and unsafe states

A state is safe if there is a safe sequence ⟨Pi1,…,Pin⟩\langle P_{i_1}, \dots, P_{i_n} \rangle: each PikP_{i_k} can obtain its remaining Need from the currently available resources plus everything held by the processes before it in the sequence, finish, and release.

Safe, unsafe, deadlocked. Every safe state is deadlock-free. An unsafe state is not necessarily deadlocked: it only means the OS can no longer guarantee completion if processes demand their maxima. Deadlocked states are a subset of unsafe states.

Algorithms

Safety algorithm

Text
SAFE(Available, Allocation, Need):
    Work <- Available
    Finish[i] <- false for all i
    repeat
        find i with Finish[i] = false and Need[i] <= Work
        if found then
            Work <- Work + Allocation[i]     -- P_i finishes and releases
            Finish[i] <- true
            append P_i to the sequence
    until no such i
    return (all Finish[i] are true), sequence

Time upper bound O(mn2)O(mn^2). Auxiliary workspace is O(n+m)O(n+m), excluding the O(nm)O(nm) input matrices; an average time requires a distribution over inputs and scan orders. Any order that picks an eligible process works: picking one never hurts, because finishing only adds to Work. The scan convention scans i=0,1,…,n−1i = 0, 1, \dots, n - 1 from the start after each choice and takes the first eligible process; other scan orders find other safe sequences, all equally valid.

Resource-request algorithm

When PiP_i requests the vector Request:

  1. If Request >> Need[i][i] in any component: error, the process exceeded its claim.
  2. If Request >> Available in any component: PiP_i waits, the resources are not there.
  3. Otherwise pretend to grant: Available −=-= Request, Allocation[i][i] +=+= Request, Need[i][i] −=-= Request. Run SAFE. If safe, grant for real; if unsafe, undo and make PiP_i wait even though the resources are free.

Avoidance versus detection. Both algorithms look alike. Safety uses Need (worst-case future demand); detection uses Request (current outstanding requests). Avoidance runs before granting; detection runs after the fact.

Mathematical explanation

Why a greedy scan suffices. If some safe sequence exists and the algorithm picks an eligible process PkP_k that is not first in it, finishing PkP_k only increases Work. Every process in the original sequence remains eligible at its turn, with PkP_k removed. So the greedy choice never closes a safe path, and the algorithm declares the state unsafe only when no safe sequence exists.

Counting safe sequences. The number is not determined by the safety algorithm; it requires enumerating orders (a depth-first search over eligible choices). In the example, P2 and P1 are forced, then all 3!=63! = 6 orders of P0, P3, P4 work because Work (4,3,2)(4, 3, 2) already covers all three remaining needs.

Worked examples

Safety check on a five-process system

Total resources (A,B,C)=(7,5,5)(A, B, C) = (7, 5, 5).

ProcessAllocationMaxNeed
P01 1 24 3 33 2 1
P12 0 13 2 21 2 1
P21 2 02 2 11 0 1
P30 1 11 3 31 2 2
P42 0 05 1 13 1 1

Allocated: (6,4,4)(6, 4, 4), so Available =(1,1,1)= (1, 1, 1).

StepEligible first (scan from P0)Work after it finishes
start1 1 1
1P2 (Need 1 0 1)2 3 1
2P1 (Need 1 2 1)4 3 2
3P0 (Need 3 2 1)5 4 4
4P3 (Need 1 2 2)5 5 5
5P4 (Need 3 1 1)7 5 5

Safe sequence ⟨P2,P1,P0,P3,P4⟩\langle P2, P1, P0, P3, P4 \rangle. Enumerating all orders, there are exactly 6 safe sequences, and every one starts with P2, P1: at the start only P2 fits, and after P2 only P1 does; the last three can then go in any order (3!=63! = 6). Work ends at the total (7,5,5)(7, 5, 5), as it must.

Banker's tables and safe sequence
Figure 1. The Allocation, Max and Need tables for P0 to P4 with Available (1, 1, 1), and the safe sequence P2, P1, P0, P3, P4 with Work growing to (2, 3, 1), (4, 3, 2), (5, 4, 4), (5, 5, 5) and (7, 5, 5).

Requests

From the state above:

RequestStep 1 (≤\le Need?)Step 2 (≤\le Available?)Pretend and checkDecision
P1 asks (0,1,0)(0, 1, 0)yesyesSafe (P2, P1, P0, P3, P4 still works)Grant
P1 asks (1,0,0)(1, 0, 0)yesyesAvailable becomes (0,1,1)(0, 1, 1); no process's Need fitsWait (unsafe)
P0 asks (1,0,0)(1, 0, 0)yesyesSame problem: P2 can no longer startWait (unsafe)
P2 asks (1,0,1)(1, 0, 1)yesyesP2 then needs nothing and can finishGrant
P4 asks (0,0,2)(0, 0, 2)no (Need C is 1)Error
P3 asks (0,2,0)(0, 2, 0)yesno (only 1 B free)Wait

Unsafe does not mean deadlocked. After pretending to give P1 the unit of A, nobody is actually blocked yet (no outstanding requests), so the detection algorithm finds no deadlock. The state is still refused, because a deadlock could follow if processes claim their maxima.

One resource type

Ten units; P0, P1, P2 have maxima 8, 3, 6 and hold 4, 1, 2, so 3 units are free and the needs are 4, 2, 4. Safe: P1 (needs 2) finishes and frees 3 units, giving 4 free; then P0 (needs 4) finishes, giving 8; then P2. If P2 is given one more unit, the state is still safe, but only in the order P1, P2, P0 (after P1 finishes, 3 units are free: enough for P2, not for P0). If P2 is given two more, only 1 unit is free and every need exceeds it: unsafe.

A state with branching safe sequences

When more than one process is eligible at several steps, the safe sequences do not reduce to one forced prefix and a factorial. Take this five-process state, with Available (3,3,2)(3, 3, 2):

ProcessAllocationMaxNeed
P00 1 07 5 37 4 3
P12 0 03 2 21 2 2
P23 0 29 0 26 0 0
P32 1 12 2 20 1 1
P40 0 24 3 34 3 1

Count by building the tree of choices, adding the Allocation of each process that finishes to Work:

  • Start, Work (3,3,2)(3, 3, 2): only P1 and P3 fit (P4 needs 4 of A).
  • After P1 and P3 in either order, Work (7,4,3)(7, 4, 3): P0, P2 and P4 all fit, and finishing any of them only adds to Work, so all 3!=63! = 6 orders work. Two prefixes give 2×6=122 \times 6 = 12 sequences.
  • After P1 then P4, Work (5,3,4)(5, 3, 4): P0 and P2 both need more A than 5, so P3 is forced, then P0 and P2 in either order: 2 sequences.
  • After P3 then P4, Work (5,4,5)(5, 4, 5): P1 is forced, then P0 and P2 in either order: 2 sequences.

Total: 12+2+2=1612 + 2 + 2 = 16 safe sequences, confirmed by enumerating all 5!=1205! = 120 orders. That scan finds ⟨P1,P3,P0,P2,P4⟩\langle P1, P3, P0, P2, P4 \rangle.

Testing a given sequence. Run the sequence and check each Need against Work at its turn.

SequenceVerdict
⟨P1,P3,P4,P2,P0⟩\langle P1, P3, P4, P2, P0 \rangleSafe
⟨P3,P4,P1,P0,P2⟩\langle P3, P4, P1, P0, P2 \rangleSafe
⟨P4,P1,P3,P0,P2⟩\langle P4, P1, P3, P0, P2 \rangleNot safe: P4 needs (4,3,1)(4, 3, 1) but Work is (3,3,2)(3, 3, 2)
⟨P1,P0,P3,P2,P4⟩\langle P1, P0, P3, P2, P4 \rangleNot safe: after P1, Work (5,3,2)(5, 3, 2) cannot cover P0's (7,4,3)(7, 4, 3)

A sequence that fails says nothing about the state as a whole: this state is safe, because some other order works.

Important properties and observations

  • Granting a request never helps safety; refusing one never hurts it.
  • With one resource type, the safety check reduces to sorting the processes by need and checking cumulatively.
  • The algorithm is conservative: it refuses some requests that would in fact have worked out.
  • Practical systems rarely use it for general resources, because maximum claims are unknown and processes come and go; the ideas appear in admission control.

Common misconceptions.

  • "Unsafe means deadlocked." Unsafe means deadlock is possible.
  • "If resources are available, the request is granted." Not if the resulting state is unsafe.
  • "The safe sequence is unique." There may be many; the task may be to exhibit one, to count them all, or to test a given sequence.

GATE examination perspective

  • Compute Need first. Need=Max−Allocation\text{Need} = \text{Max} - \text{Allocation}, and Available from the totals if not given.
  • Safe sequence questions. Show one valid order; if options are given, test each order step by step.
  • Request questions. Apply the three steps in order: claim check, availability check, pretend-and-check.
  • Counting safe sequences. Enumerate eligible choices at each step; forced prefixes often reduce the count to a factorial of the free tail.
  • Safe versus unsafe versus deadlocked. Subset relations: deadlocked ⊂\subset unsafe; safe ∩\cap deadlocked =∅= \varnothing.
  • Detection versus avoidance. Request matrix versus Need matrix.

Summary

Sources

  1. A. Silberschatz, P. B. Galvin, G. Gagne, Operating System Concepts, 10th ed., Wiley: Chapter 8, Section 8.6 Deadlock Avoidance (safe state, resource-allocation-graph algorithm, Banker's algorithm).
  2. A. S. Tanenbaum, H. Bos, Modern Operating Systems, 4th ed., Pearson: Section 6.5 Deadlock Avoidance (6.5.2 Safe and Unsafe States, 6.5.3 The Banker's Algorithm for a Single Resource, 6.5.4 The Banker's Algorithm for Multiple Resources).

Next steps