aniugne
aniugne

Reputation: 67

Why doesn't it create a deadlock?

Please refer to the code below

package com.test;

public class DeadLock {

    private void method1() {

        synchronized (Integer.class) {
            method2();
        }
    }

    private void method2() {
        synchronized (Integer.class) {
            System.out.println("hi there");
        }
    }

    public static void main(String[] args) {
        new DeadLock().method1();
    }
}

As per my understanding, the code in method2 should not be executed in any case, since method1 holds the lock on Integer.class and method2 tries to access the lock on Integer.class again. But to my surprise, the code runs fine and it prints "hi there" to the console. Can someone clarify?

Upvotes: 2

Views: 118

Answers (5)

Aaron Digulla
Aaron Digulla

Reputation: 328800

Locks are owned by threads. If your thread already owns a lock, Java assumes that you don't need to acquire it a second time and just continues.

You'll get a deadlock if you start a second thread in method1() while holding the lock and the second thread executes the method method2().

If you prefer code, then synchronized works like this:

Lock lock = Integer.class.getLock();
boolean acquired = false;
try {
    if(lock.owner != Thread.currentThread()) {
        lock.acquire();
        acquired = true;
    }

    ...code inside of synchronized block...
} finally {
    if(acquired) lock.release();
}

Here is code to demonstrate the deadlock. Just set runInThread to true:

package com.test;

public class DeadLock {

    private void method1() {

        synchronized (Integer.class) {
            boolean runInThread = false;

            if( runInThread ) {
                Thread t = new Thread() {
                    @Override
                    public void run() {
                        method2();
                    }
                };
                t.start();
                try {
                    t.join(); // this never returns
                } catch( InterruptedException e ) {
                    e.printStackTrace();
                }
            } else {
                method2();
            }
        }
    }

    private void method2() {
        System.out.println("trying to lock");
        synchronized (Integer.class) {
            System.out.println("hi there");
        }
    }

    public static void main(String[] args) {
        new DeadLock().method1();
    }
}

Upvotes: 4

EMM
EMM

Reputation: 1812

It seems you have misunderstood the concept. A method never acquires a lock, the instance on which the method is invoked serves as a lock in case of synchronized method and in case of synced block the thread acquires the lock on specified object.

Here the instance acquires the lock on Integer.class and then it goes on to execute method2.

There is no case of deadlock as in your case thread continues for the execution of the method that you're calling inside method1. So there is no deadlock that happens.

Upvotes: 3

Marek Smigielski
Marek Smigielski

Reputation: 361

As already said, one thread can access more than one synchronised blocks when no other thread already blocks it. In that situation the same thread can reenter synchronised block because it already holds it from method1.

To cause the deadlock you have to use two thread at least and two different locks. It have to access two locks in the reverse order. Check out that code:

private void method1() throws InterruptedException
{
    synchronized (Integer.class)
    {
        System.out.println(Thread.currentThread().getName() + " hi there method 1");
        Thread.sleep(1000);
        method2();
    }
}

private void method2() throws InterruptedException
{
    synchronized (Double.class)
    {
        System.out.println(Thread.currentThread().getName() + " hi there method 2");
        Thread.sleep(1000);
        method1();
    }
}

public static void main(String[] args) throws InterruptedException
{
    new Thread()
    {
        @Override
        public void run()
        {
            try
            {
                new DeadLock().method1();
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }.start();
    new DeadLock().method2();
}

Upvotes: 0

Kishan Bheemajiyani
Kishan Bheemajiyani

Reputation: 3439

 synchronized (Integer.class) {
            method2();
        }

when you calling this method2(); then its not giving lock to any kind of mehtod its continues goes to the method that you are calling means this.

private void method2() {
        synchronized (Integer.class) {
            System.out.println("hi there");
        }
    }

and after completing its returning. so there is no case of dead lock. hope this explanation helps.

Upvotes: 0

yurib
yurib

Reputation: 8147

your code is equivalent to:

synchronized (Integer.class) {
    synchronized (Integer.class) {
        System.out.println("hi there");
    }
}

if the thread acquired the lock and entered the first synchronized block it will have no problem accessing the 2nd

to produce a deadlock the call to method2 should be executed by a different thread.

Upvotes: 0

Related Questions