Synchronising twice on the same object?

JavaMultithreadingSynchronizationMutex

Java Problem Overview


I was wondering if in Java I would get any odd behaviour if I synchronise twice on the same object?

The scenario is as follows

pulbic class SillyClassName {

    object moo;
    ...
    public void method1(){
        synchronized(moo)
        {
            ....
            method2();
            ....
        }
    }

    public void method2(){
        synchronized(moo)
        {
            doStuff();
        }
    }
}

Both methods use the object and are synchronised on it. Will the second method when called by the first method stop because it's locked?

I don't think so because it's the same thread but I'm unsure of any other odd results that might occur.

Java Solutions


Solution 1 - Java

Reentrant

Synchronized blocks use reentrant locks, which means if the thread already holds the lock, it can re-aquire it without problems. Therefore your code will work as you expect.

See the bottom of the Java Tutorial page Intrinsic Locks and Synchronization.

To quote as of 2015-01…

>Reentrant Synchronization > >Recall that a thread cannot acquire a lock owned by another thread. But a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block.

Solution 2 - Java

I think we have to use reentrant lock for what you are trying to do. Here's a snippet from http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html.

>What do we mean by a reentrant lock? Simply that there is an acquisition count associated with the lock, and if a thread that holds the lock acquires it again, the acquisition count is incremented and the lock then needs to be released twice to truly release the lock. This parallels the semantics of synchronized; if a thread enters a synchronized block protected by a monitor that the thread already owns, the thread will be allowed to proceed, and the lock will not be released when the thread exits the second (or subsequent) synchronized block, but only will be released when it exits the first synchronized block it entered protected by that monitor.

Though I have not tried it, I guess if you want to do what you have above, you have to use a re-entrant lock.

Solution 3 - Java

Java appears to fully support nested locks on one object by the same thread. This means that if a thread has an outer and an inner lock on an object, and another thread tries to lock on the same object, the second thread will be suspended until both locks have been released by the first thread.

My testing was done under Java 6 SE.

Solution 4 - Java

In java, the synchronized keyword on a method basically synchronizes on the current object, so in effect it's doing what you suggest above implicitly.

You won't experience problems with synchronizing on one object in one method and then synchronizing on the same object in another method because, as you say, the current thread already holds the lock on that object.

Solution 5 - Java

No problems. In your example, (once you fix your code to get rid of the compile warnings that you'll get ;) ), the synchronization ensures that the blocks in method1 and method2 will not execute simultaneously.

That's kind of the point of synchronization. :)


Edit: Sorry, missed parts of your question, but Phill answered it. To summarize, a single thread cannot deadlock itself.

Solution 6 - Java

No, the second method will not stop if called by the first. No odd results will occur (Except a slight overhead for checking the lock. This won't matter much. From Java 6 onwards, you have lock coarsening in the JVM - Java SE 6 Performance White Paper.)

For example, take a look at source code of java.util.Vector. There are a lot of calls to other synchronized methods from within synchronized methods.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionOmar KoohejiView Question on Stackoverflow
Solution 1 - JavaLeighView Answer on Stackoverflow
Solution 2 - JavaPraveen MookoniView Answer on Stackoverflow
Solution 3 - JavaOdell DamonView Answer on Stackoverflow
Solution 4 - Javauser7094View Answer on Stackoverflow
Solution 5 - JavaJack LeowView Answer on Stackoverflow
Solution 6 - JavaRuntimeExceptionView Answer on Stackoverflow