A deadlock occurs when two or more threads stop execution waiting on each other or a shared resource. While race conditions happen generally through a deficiency of locking, deadlocks occur through incorrect or overzealous locking. Listing 13-4 shows two methods that are destined to eventually deadlock.
public class ClassA {
private ClassB that;
public void doSomething() {
synchronized(this) {
synchronized(that) {
// Do the work
}
}
}
public void doSomethingElse() {
synchronized(that) {
synchronized(this) {
// Do other work
}
}
}
}
Note the opposite orders in which the two methods acquire the locks. What happens if doSomething()
acquires the lock on the object, and doSomethingElse()
acquires the lock on that
before doSomething()
can? Both will wait for what the other has and neither will continue. Generally, locking should happen in the same order in all uses—a concept known as hierarchical locking—in order to be correct. The switch in order here is a concurrency code smell.
3.21.104.183