CPS110: Deadlock February 4, 2009 Landon Cox

advertisement
CPS110:
Deadlock
Landon Cox
February 4, 2009
Concurrency so far
 Mostly tried to constrain orderings
 Locks, monitors, semaphores
 It is possible to over-constrain too
 A must run before B
 B must run before A
 This can lead to deadlock
Definitions
 Resource
 Thing needed by a thread to do its job
 Threads wait for resources
 E.g. locks, disk space, memory, CPU
 Deadlock
 Circular waiting for resources
 Leaves threads unable to make progress
Example deadlock
 Both CPS108 and CPS110 are full
 You want to switch from 110 to 108
 Someone else wants to switch from 108 to 110
 Algorithm for switching
 Wait for spot in new class to open up
 Add new class
 Drop old class
 Problem: must add before dropping
Deadlock and starvation
 Deadlock  starvation
 Starvation = one process waits forever
Thread A
Thread B
lock (x)
lock (y)
…
unlock (y)
unlock (x)
lock (y)
lock (x)
…
unlock(x)
unlock(y)
Can deadlock occur?
Deadlock and starvation
 Deadlock  starvation
 Starvation = one process waits forever
Thread A
Thread B
lock (x)
lock (y)
lock (y) // wait for B
lock (x) // wait for A
WillCan
deadlock
deadlock
always
occur?
occur?
Common thread work pattern
Phase 1.
Phase 2.
while (not done) {
get some resources (block if necessary)
work // assume finite
}
release all resources
 Has anyone taken CPS116 (databases)?
 This is called “two-phase” locking
 Ensures “conflict-serializability”
 Still deadlock-prone
Dining philosophers
Philosopher algorithm
1) Wait for right chopstick
2) Pick up right chopstick
3) Wait for left chopstick
4) Pick up left chopstick
5) Eat
6) Put both chopsticks down
How can deadlock occur?
A
E
B
D
C
Conditions for deadlock
1. Limited resource
 Not enough for all threads simultaneously
2. Hold-and-wait
 Hold one resource, while waiting for another
3. No pre-emption
 Cannot force threads to give up resources
4. Circular chain of requests
Circular chain of requests
 Arrows
 Thread  resource it’s waiting for
 Resource  thread that’s holding it
Thread A
Resource 1
Thread B acquires Resource 1
Thread B waits for Resource 2
Thread A acquires Resource 2
Thread A waits for Resource 1
Resource 2
Thread B
Called a wait-for graph
Deadlock
 What should we do about them?
1. Ignore them
 Common OS-level solution for programs
 (OS has no control over user programs)
2. Detect-and-fix
3. Prevent
Detect-and-fix
 First part: detect
 This is easy; just scan the wait-for graph
 Second part: fix
1.
Kill first thread, take back resources by force
 Why might this be unsafe?
 Can expose inconsistent state
2.
Roll-back actions of 1 or more thread, retry
 Often used in databases
 Not always possible (some actions can’t be undone)
 E.g. can’t unsend a network message
Detect-and-fix
 Retrying during fix phase can be tricky
 If holding R and will wait for L, drop R and try again.
What could happen?
Everyone picks up R
Everyone drops R
Everyone picks up R
Everyone drops R
(and so on)
This is called “livelock.”
A
E
B
D
C
Detect-and-fix
 Retrying during fix phase can be tricky
 If holding R and will wait for L, drop R and try again.
How to prevent livelock?
Choose a winner.
How to choose a winner?
E
First to start/pick up?
What if we have priorities?
(called “priority inversion”)
e.g. Queen waiting for joker
Should Queen always win?
No, could starve the joker
A
B
D
C
Deadlock prevention
 Idea: remove one of four pre-conditions
1. Make resources unlimited




Best solution, but often impossible
Can still increase number, reduce likelihood
(larger 108 and 110 classes)
Not clear this works for locks
Deadlock prevention
2. Eliminate hold-and-wait
 Idea: move resource acquisition to beginning
Phase 1a. get all resources
Phase 1b. while (not done) {
work // assume finite
}
Phase 2. release all resources
 Two ways to avoid holding while waiting
Eliminating hold-and-wait
1.
Wait for everything to be free, then grab them all at once
Philosopher algorithm
lock
while (left chopstick busy ||
right chopstick busy) {
wait
}
pick up right chopstick
pick up left chopstick
unlock
eat
lock
drop chopsticks
unlock
Any potential problems?
Can induce starvation (neighbors alternate eating).
Eliminating hold-and-wait
2.
If you find a resource busy, drop everything, and try again
Philosopher algorithm
lock
while (1) {
while (right chopstick busy) {
wait
}
pick up right chopstick
if (left chopstick busy) {
drop right chopstick
} else {
pick up left chopstick
break
}
}
unlock
eat
lock
drop chopsticks
unlock
Issues?
Must predict what you need in advance.
Hold reservations longer than needed
Requires changes to applications.
Deadlock prevention
3. Enable pre-emption




Can pre-empt the CPU (context switch)
Can pre-empt memory (swap to disk)
Not everything can be pre-empted
Can locks be pre-empted?
 Probably not
 Must ensure that data is in consistent state
Deadlock prevention
4. Eliminate circular chain of requests
 How can we get rid of these cycles?
 Impose an ordering on resource acquisition
 E.g. must always acquire A before B
 In dining philosophers?
 Number chopsticks
 Pick up lower-numbered chopstick first
Dining philosophers
Philosopher algorithm
1) Wait for lower chopstick
2) Pick up lower chopstick
3) Wait for higher chopstick
4) Pick up higher chopstick
5) Eat
6) Put both chopsticks down
A
1
2
E
B
5
Try to create a deadlock
3
D
C
4
Universal ordering
 Why does this work?
 At some point in time
 T holds highest-numbered acquired resource
 T is guaranteed to make progress. Why?
 If T needs a higher-numbered resource, it must be free
 If T needs a lower-numbered resource, it already has it
 If T can make progress, it will eventually release all of its resources
 What if another thread acquires a higher-numbered resource?
 They just become T
 (in which case, the same reasoning as above holds)
Dining philosophers
Philosopher algorithm
1) Wait for lower chopstick
2) Pick up lower chopstick
3) Wait for higher chopstick
4) Pick up higher chopstick
5) Eat
6) Put both chopsticks down
A
1
2
E
B
5
What if E only needs one chopstick?
Only have trouble if E acquires lowernumbered chopstick before 5.
(but this is a violation of our rule)
3
D
C
4
Deadlock avoidance
 Issue with imposing global orderings
 Must change the application
 Common technique
 Requires programming discipline
Course administration
 Project 1
 Due February 18th (two weeks)
 6 groups are done with 1d
 No one has submitted 1t yet (!)
 Should be done with 1d by end of the week
 1t is a lot more work, don’t keep putting it off!
 Compiling
 g++ -o disk disk.cc thread.o
Course administration
 Remember to work on your thread library test suite too
 For each of your test cases
 Compare output of your library with thread.o
 Writing test cases
 Read through spec
 Write test cases to stress each required part
 E.g. lock() blocks if lock is already held
 Use yield() to create the right interleavings
 Read through your code
 Write test cases to exercise all lines of code
 E.g. each clause of an if/else statement
 Micro-tests are better for debugging than macro-tests
Banker’s algorithm
 Like acquiring all resources first
 (but more efficient)
Phase 1a. state max resources needed
Phase 1b. while (not done) {
get some resources (blocking if not SAFE)
work // assume finite
}
Phase 2. release all resources
Comparing banker’s algorithm
 Original
 Acquired resources if available (deadlock)
 Previous solution (no “hold-and-wait”)
 Acquired all resources or none
 Must acquire max resources to do work
 All threads doing work own their max
 Thus, all threads doing work can complete
Banker’s algorithm
 Give out resources at request time (1b)
 Request granted if it is safe
 Can grant max requests of all threads in some sequential order
 Sequential order
 One thread gets its max resources, finishes, and releases its resources
 Another thread gets its max resources, finishes, and releases, etc
Phase 1a. state max resources needed
Phase 1b. while (not done) {
get some resources (blocking if not SAFE)
work // assume finite
}
Phase 2. release all resources
Example
 Bank
 Has $6000 to loan
 Customers
 Establish credit limits (max resources)
 Borrow money (up to their limit)
 Return all money at the end
Example: Solution 1
 Bank gives money on request, if available
 For example
 Ann asks for credit line of $2000
 Bob asks for credit line of $4000
 Cat asks for credit line of $6000
 Can bank approve each of these lines?
 (assuming it gives money, if available)
Example: Solution 1
 No. Consider:
 Ann takes out $1000 (bank has $5000)
 Bob takes out $2000 (bank has $3000)
 Cat takes out $3000 (bank is empty)
 Bank has no money
 Ann, Bob, and Cat could all ask for $
 None would be able to finish (deadlock)
Example: Solution 1
 This only works if we wait to approve credit lines
 For example
 Ann asks for credit line of $2000
 Bank approves
 Bob asks for credit line of $4000
 Bank approves
 Cat asks for credit line of $6000
 Bank must make Cat wait until Ann or Bob finish
 Sum of all max resource needs of all current threads
 Must not exceed the total resources
Example: Solution 2
 Bank says ok to all credit line requests
 Customers may wait for resources
 Bank ensures no deadlocks
 For example




Ann asks for credit limit of $2000
Bob asks for credit limit of $4000
Cat asks for credit limit of $6000
Bank approves all credit limits
Example: Solution 2
 Ann takes out $1000 (bank has $5000)
 Bob takes out $2000 (bank has $3000)
 Cat wants to take out $2000
 Is this allowed?
 Bank would be left with $1000
 Ann would still be guaranteed to finish
 (could take out another $1000)
 On finish, bank would have $2k
 This is enough to ensure that Bob can finish
Example: Solution 2
 Ann takes out $1000 (bank has $5000)
 Bob takes out $2000 (bank has $3000)
 Cat wants to take out $2500
 Is this allowed?
 Bank would be left with $500
 Can’t guarantee that any threads will finish
Banker’s algorithm
 Allows resources to be overcommitted
 How can we apply this to dining philosophers?
 Put all chopsticks in the middle of the table
 Max resource need for each philosopher is 2
 Grant requests, unless
 There is only one chopstick left and nobody has 2
 Nice algorithm, but few people use it. Why?
 You rarely know what you’ll need in advance
 Doesn’t really make sense for locks (no “generic lock”)
Download