Here is an example of a dead end that does not use wait . As long as you have synchronization, there is a chance of a dead end.
public class Deadlock { static class Deadlocker { private Deadlocker other; public void setOther(Deadlocker other) { this.other = other; } synchronized void doSomethingWithOther() { try { Thread.sleep(1); } catch (InterruptedException e) { } other.doSomething(); } synchronized void doSomething() { } } public static void main(String[] args) { final Deadlocker d1 = new Deadlocker(); final Deadlocker d2 = new Deadlocker(); d1.setOther(d2); d2.setOther(d1); Thread t1 = new Thread() { public void run() { d1.doSomethingWithOther(); } }; Thread t2 = new Thread() { public void run() { d2.doSomethingWithOther(); } }; t1.start(); t2.start(); } }
A deadlock occurs when t1 is in d1.doSomethingWithOther() (and therefore has a lock on d1 ), and t2 is in d2.doSomethingWithOther() (and therefore has a lock on d2 ). When each thread tries to call doSomething() on the object, lock is turned on for the other thread, they ended up stuck waiting for each other.
Note that deadlock does not necessarily include only two threads. You can have a loop of any size. Worse, as soon as a deadlock occurs, any other thread that tries to obtain a lock that the deadlock is already holding will eventually become actually blocked, even without being in a loop.
source share