Deadlocks
and Livelocks
So far,
we’ve demonstrated some fundamental ways to share access to resources between
threads. We now need to discuss the situations where strategies might go wrong.
First is
the deadlock, where two or more
threads cannot make progress because the resources that they need are held by
the other threads. It is easiest to explain this with an example. Suppose two
threads need to acquire mutex locks A and B to complete some task. If thread 1 has already
acquired lock A and
thread 2 has already acquired lock B, then A cannot make forward progress because it is waiting
for lock B, and
thread 2 cannot make
progress because it is waiting for lock A. The two threads are deadlocked. Listing 4.13 shows this situation.
Listing 4.13 Two Threads in a Deadlock
The best
way to avoid deadlocks is to ensure that threads always acquire the locks in
the same order. So if thread 2 acquired the locks in the order A and then B, it would stall while waiting
for lock A without
having first acquired lock B. This would enable thread 1 to acquire B and then eventually release both
locks, allowing thread 2 to make progress. A livelock traps threads in an unending loop releasing and acquiring
locks. Livelocks
can be
caused by code to back out of deadlocks. In Listing 4.14, the programmer has
tried to implement a mechanism that avoids deadlocks. If the thread cannot
obtain the second lock it requires, it releases the lock that it already holds.
The two
routines update1() and update2() each
have an outer loop. Routine update1() acquires lock A and then attempts to acquire lock B, whereas update2() does this
in the opposite order. This is a classic deadlock opportunity, and to avoid it,
the developer has written some code that causes the held lock to be released if
it is not pos-sible to acquire the second lock. The routine canAquire(), in this
example, returns immediately either having acquired the lock or having failed
to acquire the lock.
Listing 4.14 Two Threads in a Livelock
If two
threads encounter this code at the same time, they will be trapped in a
livelock of constantly acquiring and releasing mutexes, but it is very unlikely
that either will make progress. Each thread acquires a lock and then attempts
to acquire the second lock that it needs. If it fails to acquire the second
lock, it releases the lock it is holding, before attempting to acquire both
locks again. The thread exits the loop when it manages to successfully acquire
both locks, which will eventually happen, but until then, the application will make no forward progress.
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2024 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.