Deadlocks Chapter7 Notes
Deadlocks Chapter7 Notes
CHAPTER 7
DEADLOCKS
Detailed Study Notes
Operating System Concepts — Silberschatz, Galvin, Gagne
Page 1 of 29
OS Concepts — Chapter 7 Deadlocks
Table of Contents
TOC \h \o "1-3"
Page 2 of 29
OS Concepts — Chapter 7 Deadlocks
1. Introduction to Deadlocks
In a multiprogramming environment, many processes run together and compete for a limited number of
resources (CPU, memory, files, printers, locks, etc.). A process that needs a resource must request it; if
the resource is unavailable, the process is forced to wait. Sometimes a process is left waiting forever
because the very resources it needs are being held by other processes that are themselves stuck waiting.
This permanent stuck condition is called a deadlock.
• Most real operating systems (Linux, Windows) do not provide built-in deadlock prevention. It is
the application/programmer's job to write deadlock-free code.
• Deadlock problems are becoming more common because of: larger numbers of processes,
multithreaded programs, more system resources, and a shift from batch systems toward long-
lived file/database servers.
• This chapter has two core objectives: (1) describe what deadlocks are and how they prevent
processes from completing, and (2) present methods to prevent, avoid, detect, and recover from
deadlocks.
• Resource type: a category of resource, e.g., CPU, printer, file, semaphore, mutex lock.
• Resource instance: one physical/logical unit of that type. Example: if a system has 2 CPUs, the
resource type “CPU” has 2 instances; 5 printers means resource type “printer” has 5 instances.
If a process requests an instance of a resource type, any instance of that type must be able to satisfy the
request — otherwise the resource type classes are not defined properly. Example: two printers on
different floors (9th floor vs basement) may need to be treated as separate resource classes if users care
which one they get, even though both are “printers.”
Locks as resources
Mutex locks and semaphores (Chapter 5 synchronization tools) are also system resources and a very
common source of deadlock. Since each lock typically protects one specific data structure (a queue,
a linked list, etc.), each lock is usually given its own resource class — so resource-type definition is
not an issue for locks.
Page 3 of 29
OS Concepts — Chapter 7 Deadlocks
1. Request: the process asks for the resource. If it cannot be granted immediately (already in use),
the requesting process must wait.
2. Use: the process operates on the resource (e.g., prints on the printer).
3. Release: the process gives the resource back.
These steps map to actual system calls / library calls:
The operating system maintains a system table that records, for every resource, whether it is free or
allocated, and to which process. If a process requests a resource already allocated elsewhere, it is added
to a queue of processes waiting for that resource.
Page 4 of 29
OS Concepts — Chapter 7 Deadlocks
Developers of multithreaded code must be careful: locking tools (mutexes, semaphores from Chapter 5)
prevent race conditions but, if locks are acquired/released carelessly, they can themselves cause
deadlock — as in the dining-philosophers problem.
pthread_mutex_init(&first_mutex, NULL);
pthread_mutex_init(&second_mutex, NULL);
Two threads are created: thread_one runs do_work_one(), thread_two runs do_work_two().
Page 5 of 29
OS Concepts — Chapter 7 Deadlocks
pthread_mutex_unlock(&first_mutex);
pthread_mutex_unlock(&second_mutex);
pthread_exit(0);
}
thread_one acquires locks in order (first_mutex, second_mutex); thread_two acquires them in the
reverse order (second_mutex, first_mutex). If thread_one grabs first_mutex while, at almost the same
moment, thread_two grabs second_mutex — both threads now wait forever for the lock the other is
holding. Deadlock.
4. Mutual exclusion. At least one resource must be held in a non-sharable mode — only one process
can use it at a time. If another process requests it, that requester must wait until it is released.
5. Hold and wait. A process must be holding at least one resource while simultaneously waiting to
acquire additional resources that are currently held by other processes.
6. No preemption. Resources cannot be forcibly taken away. A resource can only be released
voluntarily by the process holding it, after that process has finished using it.
7. Circular wait. There must exist a set of waiting processes {P0, P1, ..., Pn} such that P0 is waiting for
a resource held by P1, P1 is waiting for a resource held by P2, …, P(n−1) is waiting for a resource
held by Pn, and Pn is waiting for a resource held by P0 — a cycle of waiting.
Page 6 of 29
OS Concepts — Chapter 7 Deadlocks
Page 7 of 29
OS Concepts — Chapter 7 Deadlocks
• P1 → R1 → P2 → R3 → P3 → R2 → P1
• P2 → R3 → P3 → R2 → P2
Here, P1, P2, and P3 are genuinely deadlocked: P2 waits on R3 (held by P3); P3 waits on R2 (held by P1
or P2); P1 waits on R1 (held by P2). Nobody can proceed.
Summary takeaway
No cycle in the RAG ⇒ system is not in a deadlocked state, guaranteed. A cycle merely signals that
deadlock is possible — you must check whether other available instances of the involved resources
can break the cycle.
8. Prevention or avoidance: use a protocol that guarantees the system will NEVER enter a
deadlocked state in the first place.
9. Detection and recovery: allow deadlocks to happen, but detect them when they occur, then
recover.
10. Ignore the problem entirely: pretend deadlocks never occur (the “ostrich algorithm” approach).
Some researchers argue that no single approach is suitable for the entire range of resource-allocation
problems an OS faces. In practice, the basic approaches can be combined, choosing the best technique
for each class of resource in the system.
Page 8 of 29
OS Concepts — Chapter 7 Deadlocks
• Deadlock avoidance: requires the OS to have extra advance information about which resources
each process will need and use over its lifetime. With this knowledge, the OS decides, for each
individual request, whether granting it would be safe — considering currently available resources,
resources already allocated to each process, and each process's future requests/releases.
Despite sounding reckless, this approach is used by most operating systems for practical economic
reasons:
Page 9 of 29
OS Concepts — Chapter 7 Deadlocks
• Protocol 1 — Request everything up front: each process must request and be allocated ALL the
resources it will ever need before it begins executing. This can be implemented by requiring all
resource-request system calls to precede every other system call.
• Protocol 2 — Request only when holding nothing: a process may request resources only when it
currently holds none. It can request some resources, use them, but before requesting ANY
additional resource it must first release everything it currently holds.
• Under Protocol 1: the process must request the DVD drive, the disk file, AND the printer all at
once at the start. It will then hold the printer for its entire run, even though it is only actually
needed right at the end — wasteful.
• Under Protocol 2: the process first requests only the DVD drive and disk file, copies the data, then
releases both. It then requests the disk file and printer, copies to the printer, and releases both
before terminating.
11. Implicit-release protocol: if a process holding some resources requests another resource that
cannot be granted immediately, then ALL resources currently held by that process are preempted
(implicitly released). These preempted resources get added to the list of resources the process is
now waiting for. The process restarts only once it can regain both its old resources and the newly
requested ones.
12. Steal-from-a-waiter protocol: when a process requests resources, first check availability. If
available, allocate them. If not, check whether the desired resources are held by some OTHER
process that is itself currently waiting for additional resources. If so, preempt the desired
resources from that waiting process and give them to the requester. If the resources are neither
free nor held by a waiting process, the requester must wait — and while waiting, some of ITS
resources may, in turn, get preempted if another process requests them. A process resumes only
Page 10 of 29
OS Concepts — Chapter 7 Deadlocks
once it regains the new resources requested plus any of its own resources that were preempted
while it waited.
Formally: let R = {R1, R2, ..., Rm} be the set of resource types. Define a one-to-one function F: R → N (the
natural numbers) that assigns each resource type a unique number, letting us compare any two
resources and determine an order between them. Example assignment:
Resource Type F( )
Tape drive 1
Disk drive 5
Printer 12
Protocol rule: a process can initially request any number of instances of some resource type Ri. After
that, it may request instances of resource type Rj if and only if F(Rj) > F(Ri). So, using the table above, a
process wanting both the tape drive and printer must request the tape drive first, then the printer (since
F(tape drive)=1 < F(printer)=12).
Alternative equivalent formulation: a process requesting an instance of Rj must first have released any
resource Ri such that F(Ri) ≥ F(Rj). Also note: if several instances of the SAME resource type are needed,
they must all be requested in a single combined request.
F(R0) < F(R1) < F(R2) < ... < F(Rn) < F(R0)
By transitivity this implies F(R0) < F(R0), which is impossible. Therefore no circular wait can exist under
this protocol. ∎
Page 11 of 29
OS Concepts — Chapter 7 Deadlocks
• witness dynamically tracks the relationship between lock-acquisition orders observed across the
system.
• Example: if thread_one is first to acquire locks, doing so in order (1) first_mutex, (2)
second_mutex — witness records that first_mutex must always precede second_mutex.
• If thread_two later attempts to acquire the same locks in the opposite order, witness generates a
warning message on the system console, flagging the potential deadlock.
Caveat — lock ordering can still fail with dynamically acquired locks
Imposing a lock ordering does NOT guarantee deadlock prevention if locks are acquired dynamically (i.e.,
which lock object you need is only known at runtime). Classic example — a bank-transfer function
between two arbitrary accounts:
acquire(lock1);
acquire(lock2);
withdraw(from, amount);
deposit(to, amount);
release(lock2);
release(lock1);
}
Page 12 of 29
OS Concepts — Chapter 7 Deadlocks
Even though this function always acquires “from’s lock” before “to’s lock” in source-code order,
deadlock is still possible if two threads invoke transaction() with the SAME two accounts in transposed
(reversed) order, e.g.:
Deadlock avoidance takes a different approach: it requires additional advance information about how
each process will request resources. Example: in a system with one tape drive and one printer, the
system might know in advance that process P will request the tape drive first, then the printer, before
releasing both; while process Q will request the printer first, then the tape drive. With full knowledge of
each process's complete future sequence of requests and releases, the system can decide, for every
individual request, whether the requesting process should be made to wait in order to avoid a possible
FUTURE deadlock.
Algorithms in this family differ in how much and what type of advance information they require. The
simplest and most practically useful model requires only that each process declare the maximum
number of resource instances of each type it might ever need.
Definition
A state is safe if the system can allocate resources to every process (up to each one's declared
maximum) in SOME order, and still avoid deadlock for all of them.
More formally: a system is in a safe state only if a safe sequence exists.
A sequence of processes <P1, P2, ..., Pn> is a safe sequence for the current allocation state if, for every
Pi, the resource requests Pi could still possibly make can be satisfied using the currently available
resources PLUS the resources currently held by all Pj where j < i. If Pi's needs aren't immediately
available, Pi can simply wait until all those earlier Pj processes finish and release their resources; once
they finish, Pi can obtain everything it needs, complete, and release its own resources — letting P(i+1)
proceed the same way, and so on down the line.
Page 13 of 29
OS Concepts — Chapter 7 Deadlocks
Concept Relationship
Unsafe state NOT always a deadlock — may or may not lead to one, depending on
what the processes actually do next.
P0 10 5
P1 4 2
P2 9 2
At t0 this is a SAFE state, because the sequence <P1, P0, P2> works:
• P1 needs at most 2 more (4 max − 2 held); 3 are free — grant them. P1 finishes and returns all 4,
leaving 5 free.
• P0 needs at most 5 more (10 max − 5 held); 5 are free — grant them. P0 finishes and returns all
10, leaving 10 free.
• P2 needs at most 7 more (9 max − 2 held); 10 are free — grant them. P2 finishes and returns all 9,
leaving all 12 free again.
Page 14 of 29
OS Concepts — Chapter 7 Deadlocks
The lesson
The mistake was granting P2's request for that ONE additional tape drive without first checking
whether doing so would still leave the system in a safe state. If the system had instead made P2
WAIT until either P0 or P1 finished and released its resources, the deadlock would have been
completely avoided. This is exactly the discipline a deadlock-avoidance algorithm enforces
automatically: it grants a request only if doing so leaves the system in a safe state; otherwise the
requester waits, even if the resource is technically available right now.
Consequence: in this scheme, even if a process requests a resource that IS currently available, it may still
be forced to wait (because granting it now would create an unsafe state). This means resource
utilization can be lower than it otherwise would be — the same fundamental trade-off seen with
deadlock prevention, just applied more surgically.
All of a process's claim edges must, in principle, be added to the graph before that process even starts
executing (resources must be “claimed a priori”). This requirement can be relaxed somewhat: a claim
edge Pi→Rj may be added to the graph at any time, as long as ALL of the edges currently associated with
Pi are themselves still claim edges (i.e., Pi hasn't actually started making real requests yet).
• No cycle would result → granting the resource leaves the system in a safe state → grant it.
• A cycle WOULD result → granting would put the system in an unsafe state → Pi must wait.
Page 15 of 29
OS Concepts — Chapter 7 Deadlocks
Operating rule: when a NEW process enters the system, it must declare the maximum number of
instances of each resource type it could ever need (this number cannot exceed the system total). When
any process requests a set of resources, the system must determine whether granting that allocation
would leave the system in a safe state. If yes — grant immediately. If no — the process must wait until
enough other resources are released.
Notation used throughout: for vectors X and Y of length n, X ≤ Y means X[i] ≤ Y[i] for every i. (Example: if
X = (1,7,3,2) and Y = (0,3,2,1), then Y ≤ X.) And Y < X means Y ≤ X and Y ≠ X. We also treat each row of
Allocation and Need as a vector, written Allocationi and Needi: Allocationi is the resources currently
allocated to Pi, and Needi is the additional resources Pi may still request.
13. Initialize: Let Work (length m) and Finish (length n) be working vectors. Set Work = Available, and
Finish[i] = false for every i = 0, 1, …, n−1.
14. Find a candidate process: find an index i such that BOTH (a) Finish[i] == false AND (b) Needi ≤
Work. If no such i exists, go to step 4.
15. Simulate completion: Work = Work + Allocationi; Finish[i] = true; then go back to step 2.
16. Check result: if Finish[i] == true for ALL i, the system is in a safe state.
Computational cost: this safety algorithm requires on the order of m × n² operations to determine
whether a given state is safe (Practice Exercise 7.5 asks you to prove this bound).
Page 16 of 29
OS Concepts — Chapter 7 Deadlocks
17. Validate against declared maximum: if Requesti ≤ Needi, proceed to step 2. Otherwise, raise an
error — the process has exceeded its own declared maximum claim.
18. Check availability: if Requesti ≤ Available, proceed to step 3. Otherwise, Pi must wait, since the
resources simply aren't there yet.
19. Tentatively grant and test safety: pretend the resources have been allocated by updating the
state:
If the RESULTING state (after this tentative update) is safe according to the Safety Algorithm, the
transaction is finalized and Pi really is allocated those resources. But if the new state turns out to be
unsafe, then Pi must wait for its Requesti, and the system rolls the state back to exactly what it was
before (undoing the tentative update).
P1 200 322
P2 302 902
P3 211 222
P4 002 433
Process Need (A B C)
P0 743
P1 122
P2 600
P3 011
Page 17 of 29
OS Concepts — Chapter 7 Deadlocks
Process Need (A B C)
P4 431
Claim: this state IS safe. The sequence <P1, P3, P4, P2, P0> satisfies the safety criteria (each process's
Need can be met by Available plus what's freed by the processes before it in the sequence).
P1 302 020
P2 302 600
P3 211 011
P4 002 431
Running the safety algorithm on this NEW tentative state finds that the sequence <P1, P3, P4, P0, P2>
satisfies safety. Therefore the new state IS safe, and P1's request can be granted immediately.
Two more requests that CANNOT be granted from this new state
A request for (3,3,0) by P4 cannot be granted, simply because the resources are not available (fails
the Available check at step 2 of the Resource-Request Algorithm).
A request for (0,2,0) by P0 CANNOT be granted either, even though the resources ARE technically
available right now — because granting it would push the system into an unsafe state. This is the
entire point of the algorithm: availability alone is not sufficient justification to grant a request.
Page 18 of 29
OS Concepts — Chapter 7 Deadlocks
As before, a deadlock exists in the system if and only if the wait-for graph contains a cycle. The system
periodically maintains this graph and invokes a cycle-search algorithm on it. Detecting a cycle in a graph
with n vertices requires on the order of n² operations.
Structure Meaning
The ≤ relation between vectors is defined exactly as in the banker's algorithm. We again treat matrix
rows as vectors: Allocationi and Requesti. This detection algorithm investigates every possible allocation
sequence for the processes that still remain to be completed — compare it directly with the banker's
safety algorithm.
22. Initialize: Work = Available. For each i = 0, …, n−1: if Allocationi ≠ 0, set Finish[i] = false; otherwise
set Finish[i] = true (processes holding nothing are trivially treated as already ‘finished’ for this
algorithm, since they can't be part of a deadlock from holding nothing).
23. Find a candidate: find index i such that BOTH (a) Finish[i] == false AND (b) Requesti ≤ Work. If no
such i exists, go to step 4.
24. Simulate completion: Work = Work + Allocationi; Finish[i] = true; go back to step 2.
25. Conclude: if Finish[i] == false for SOME i (0 ≤ i < n), the system IS in a deadlocked state. Moreover,
every process Pi with Finish[i] == false is specifically one of the deadlocked processes.
Cost: this detection algorithm requires on the order of m × n² operations to determine whether the
system is currently deadlocked.
Page 19 of 29
OS Concepts — Chapter 7 Deadlocks
P1 200 202
P2 303 000
P3 211 100
P4 002 002
Running the detection algorithm finds the sequence <P0, P2, P3, P1, P4> achieves Finish[i] == true for
every i — so the system is NOT deadlocked.
Process Request (A B C)
P0 000
P1 202
P2 001
P3 100
P4 002
Now the system IS deadlocked. We can still reclaim the resources held by P0 (since Request0 = 0 ≤ Work
trivially), but after doing so, the available pool is still not sufficient to satisfy ANY of the remaining
processes' requests. The deadlock consists of processes P1, P2, P3, and P4.
Page 20 of 29
OS Concepts — Chapter 7 Deadlocks
Key structural insight: deadlocks only occur when SOME process makes a request that cannot be
granted immediately — and that exact request may be the final link that completes a chain of waiting
processes into a cycle.
• Abort ALL deadlocked processes: this definitely breaks the deadlock cycle, but at great expense —
these processes may have been computing for a long time, and all that partial work is discarded
and will likely need to be recomputed from scratch later.
Page 21 of 29
OS Concepts — Chapter 7 Deadlocks
• Abort ONE process at a time, repeatedly, until the cycle breaks: this incurs considerable
overhead too, since the deadlock-detection algorithm must be re-invoked after EACH single
termination, just to check whether any processes remain deadlocked.
34. Selecting a victim: which resources, and which processes, should be preempted? As with
termination, we want to minimize cost — common cost factors include how many resources a
deadlocked process is currently holding and how much CPU time it has already consumed.
35. Rollback: once a resource is preempted from a process, that process clearly cannot continue
normal execution — it's now missing something it needs. We must roll it back to some earlier
SAFE state and restart it from there. Because determining exactly what a safe rollback state
actually is can be difficult in general, the simplest practical solution is total rollback: just abort the
process entirely and restart it from scratch. A more surgical (partial) rollback — only as far back as
strictly necessary to break the deadlock — is more efficient but requires the system to track much
more detailed state information about every running process.
36. Starvation: how do we guarantee starvation does not occur — i.e., that resources are not always
preempted from the very same unlucky process every time? If victim selection is based purely on
cost factors, the same process might repeatedly get picked as the cheapest victim, and as a result
it NEVER actually completes its task. Any practical system must guard against this. The standard
fix: explicitly factor the NUMBER OF PRIOR ROLLBACKS into the cost calculation, so a process that
has already been a victim many times becomes progressively less likely to be chosen again.
Page 22 of 29
OS Concepts — Chapter 7 Deadlocks
Core definition
A deadlocked state occurs when two or more processes are waiting indefinitely for an event that
can be caused only by one of those very same waiting processes.
37. Use a protocol to PREVENT or AVOID deadlocks — guaranteeing the system never enters a
deadlocked state at all.
38. Allow deadlocks to occur, DETECT them, then RECOVER from them.
39. IGNORE the problem entirely — pretend deadlocks never happen. This is the approach actually
used by most real operating systems, including Linux and Windows.
A deadlock can occur only if all FOUR necessary conditions hold at once: mutual exclusion, hold and
wait, no preemption, and circular wait. Prevention works by guaranteeing at least one of these can
never hold.
Deadlock AVOIDANCE (rather than prevention) requires the OS to have a priori information about how
each process will use resources. The banker's algorithm is the canonical example, requiring advance
knowledge of the maximum number of instances of each resource class every process might request.
Where preemption is the chosen recovery method, three issues must always be addressed: selecting a
victim, rollback, and starvation. Systems that select victims purely by cost factors risk starving the same
unlucky process repeatedly, so it never completes.
Mutual exclusion Make resource sharable (e.g., read-only Many resources (mutex locks) are
files). intrinsically non-sharable — mostly
not a usable strategy.
Page 23 of 29
OS Concepts — Chapter 7 Deadlocks
Hold and wait Request all resources up front, OR Low resource utilization; possible
release everything before requesting starvation.
more.
No preemption Preempt (implicitly release) a waiting Only works for easily save/restorable
process's resources; restart it once it resources (CPU registers, memory) —
regains old + new resources. not locks/semaphores.
Circular wait Impose a total ordering F on resource Requires discipline from developers;
types; request only in increasing order. dynamic lock acquisition can still
cause deadlock (e.g., bank transfer
example).
Advance info No — just constrains Yes — max future need No advance info needed.
needed? request style. per process.
When deadlock can Never (guaranteed). Never (guaranteed, via Can actually happen;
occur Safe State checks). caught afterward.
Resource utilization Often low. Can be low (rejects safe- Generally higher — no
looking requests too). restriction until problem
found.
Key algorithm(s) Resource ordering (F Safe State check; RAG Wait-for graph (1
function). algorithm (1 instance); instance); m×n² detection
Banker's Algorithm algorithm (multi-
(multi-instance). instance).
Page 24 of 29
OS Concepts — Chapter 7 Deadlocks
Deadlock A set of processes each waiting for an event only another process in that
same set can cause.
Request edge (Pi→Rj) Pi has asked for an instance of Rj and is currently waiting.
Claim edge (dashed, Pi→Rj) Pi might request Rj at some future point (used only in avoidance, single-
instance case).
Safe state A state from which a safe sequence exists, guaranteeing every process can
eventually finish without deadlock.
Safe sequence An ordering of processes such that each one's remaining needs can be met
by available + already-held (by earlier processes) resources.
Wait-for graph RAG with resource nodes removed/collapsed; cycle = deadlock (single-
instance case only).
Witness A FreeBSD lock-order verifier tool that warns when locks are acquired out of
an established order.
Page 25 of 29
OS Concepts — Chapter 7 Deadlocks
7.1 Real-world (non-computer) analogies of deadlock — tests whether you grasp the abstract pattern
(e.g., traffic, bureaucratic paperwork loops, social etiquette deadlocks) beyond just OS resources.
7.2 Tests the key distinction: unsafe ≠ deadlocked. Asks you to show a process sequence from an
unsafe state that still completes successfully without deadlock — proving unsafe states are merely
risky, not doomed.
7.3 Direct application of the Banker's Algorithm: compute Need = Max − Allocation, run the Safety
Algorithm to test if the state is safe, then run the Resource-Request Algorithm for a hypothetical
request from P1.
7.4 Compares a 'single master lock F containing everything' (containment) scheme against the circular-
wait total-ordering scheme of 7.4.4 — tests understanding that containment is really a
DEGENERATE case of total ordering (F is simply ordered before everything else).
7.5 Asks for a formal complexity proof of the Safety Algorithm — reinforces WHY it's O(m×n²): the
outer loop runs up to n times (once per process found-and-finished), and each pass scans up to n
processes checking an m-length Need vector.
7.6 A cost-benefit analysis exercise: weighs the overhead of installing a deadlock-avoidance scheme
(10% slower execution, 20% worse turnaround) against the current cost of deadlocks (lost CPU-time
worth of aborted jobs twice a month) — tests applied economic reasoning around deadlock
handling, echoing Section 7.3's 'ignore the problem' discussion.
7.7 Asks whether a system can DETECT starvation, and what to do about it if so — distinguishes
deadlock detection from the separate (related but different) problem of starvation detection.
7.8 Walks through a 'steal resources from a blocked process' policy (the no-preemption-removal
protocol from 7.4.3) with concrete numbers, then asks whether deadlock or indefinite blocking
(starvation) can still occur under that exact policy.
7.9 Tests whether you understand the DEEP similarity (and key difference) between the Banker's safety
algorithm and the deadlock-DETECTION algorithm — by asking if simply redefining Max as Waiting
+ Allocation lets you reuse the safety-algorithm code as a detector. (Hint: detection algorithm uses
CURRENT requests, not a declared future maximum — the semantics genuinely differ even though
the code shape is similar.)
7.1 Tests the boundary case: can a SINGLE single-threaded process ever deadlock by itself? (Generally
0 no for the classic definition, since circular wait requires ≥ 2 entities waiting on each other — though
self-deadlock on a non-reentrant lock a thread already holds is a related but distinct phenomenon
worth discussing.)
Page 26 of 29
OS Concepts — Chapter 7 Deadlocks
7.1 Traffic-deadlock diagram (Figure 7.10): identify all FOUR necessary conditions in a real traffic
1 gridlock, then propose a simple traffic rule that breaks one of them (commonly: don't enter an
intersection unless your exit is clear — a no-hold-and-wait-style rule).
7.1 Reader–writer locks and the four conditions: tests whether shared (reader) access changes the
2 mutual-exclusion analysis, and whether deadlock is still possible purely from writer-vs-writer or
writer-vs-reader ordering conflicts across MULTIPLE such locks.
7.1 Revisits the Pthread mutex example (Figure 7.4): asks you to explain the CPU scheduler's role —
3 since deadlock there depends entirely on the interleaving/timing the scheduler happens to
produce, not on the code alone.
7.1 Asks you to actually FIX the transaction() function from Figure 7.5 so transposed-argument calls
4 can't deadlock — the standard fix is to always acquire locks in a FIXED canonical order (e.g., by
comparing account IDs/addresses) regardless of the 'from'/'to' argument order.
7.1 Compares circular-wait-ordering (a prevention technique) against avoidance schemes like the
5 banker's algorithm, specifically on (a) runtime overhead and (b) system throughput — ordering
schemes are typically cheaper to check but more restrictive; avoidance is more flexible but costs
more per request.
7.1 Six sub-questions about safely modifying Banker's-Algorithm inputs (Available, Max per process,
6 number of processes) WITHOUT reintroducing deadlock risk — tests which changes are always safe
(e.g., increasing Available) vs. which require re-running the safety check (e.g., increasing one
process's Max, since that process might now claim more than the system can ever supply).
7.1 Classic 'deadlock-free by resource-count arithmetic' proofs — show that if total resources, number
7& of processes, and per-process maximum needs satisfy certain inequalities (e.g., sum of max needs <
7.1 m + n), deadlock is mathematically impossible regardless of timing.
8
7.1 Dining-philosophers variants with chopsticks pooled centrally rather than fixed per-philosopher —
9& tests designing a simple ADMISSION RULE for grants (how many of the shared pool can be handed
7.2 out before a request must be refused) that provably avoids deadlock, first for 2 chopsticks per
0 philosopher, then for 3.
7.2 Tests the (false) intuition that 'multi-resource banker's algorithm = single-resource banker's
1 algorithm applied to each type separately' — asks for a counter-example showing that satisfying
safety for EACH resource type individually does NOT guarantee a combined safe state. (The
resource types interact through shared process Need vectors.)
7.2 More worked banker's-algorithm numeric problems: build Need from Allocation/Max, test multiple
2& candidate Available vectors for safety (showing a valid completion order or proving none exists),
7.2 and evaluate specific incoming requests.
3
7.2 Asks for the specific optimistic assumption embedded in the Detection Algorithm (Section 7.6.2,
4 step 3) — that any process whose current request CAN be satisfied will need NO further resources
and will finish; and how this assumption can be violated (the process makes ANOTHER request later
Page 27 of 29
OS Concepts — Chapter 7 Deadlocks
Dijkstra (1965) One of the earliest and most influential deadlock researchers;
originated the banker's algorithm for a SINGLE resource type.
Habermann (1969) Extended the banker's algorithm from a single resource type to
MULTIPLE resource types.
Coffman, Elphick & Shoshani Presented the deadlock-detection algorithm for multiple instances of
(1971) a resource type (Section 7.6.2).
Page 28 of 29
OS Concepts — Chapter 7 Deadlocks
Page 29 of 29