Search code examples
javamultithreadingdeadlock

Is it possible to write a guaranteed classic deadlock with synchronized methods?


I was asked at an interview to write java code which is guaranteed deadlock. I wrote a standard code which presents at every Java book, like create 2 threads and call synchronized methods at different order, sleep a little before call the 2nd.

Of course this stuff didn't satisfy the interviewers, so now I'm proceeding to figure the solution out.

I discovered a piece of code:

public class Lock implements Runnable {

    static {
        System.out.println("Getting ready to greet the world");
        try {
            Thread t = new Thread(new Lock());
            t.start();
            t.join();
        } catch (InterruptedException ex) {
            System.out.println("won't see me");
        }
    }

    public static void main(String[] args) {
        System.out.println("Hello World!");
    }

    public void run() {
        try {
            Thread t = new Thread(new Lock());
            t.start();
            t.join();
        } catch (InterruptedException ex) {
            System.out.println("won't see me");
        }
    }

}

But I'm not sure if this code satisfied them? Sure. The code never ends execution, but is it a true deadlock? Aren't deadlocks about synchronization? And, for example, I can also write an endless cycle, put a Thread.sleep inside and name it a "deadlock".

So the question is: is it possible to write a classic deadlock using synchronized methods but 100% guaranteed? (Please don't tell me about very, very, very likely deadlock cases. I know it.)

Thanks.


Solution

  • Create two resources, and have each thread try to get one before releasing the other, but in different orders. For instance:

    CountDownLatch a = new CountDownLatch (1);
    CountDownLatch b = new CountDownLatch (1);
    
    void one() throws InterruptedException {
      a.await();
      b.countDown();
    }
    
    void two() throws InterruptedException {
      b.await();
      a.countDown();
    }
    

    The thread that runs one can't release b, because it's waiting for a. It'll wait forever, because the thread that runs two can't release a because it's waiting for b.

    One or the classic deadlock scenarios is when you acquire locks in reverse order.