[concurrency-interest] Are synchronized methods safer than synchronized blocks?

Dmytro Sheyko dmytro_sheyko at hotmail.com
Mon Dec 14 09:42:00 EST 2009


Hi,

It seems that in practice infinite loop does not occur because monitorexit (for some reason) does not throw IllegalMonitorStateException.
The program proves this.

// test/Main.java
package test;

public class Main {

    public static void main(String... args) {
        try {
            new Main().useSynchronizedMethod();
            System.err.println("method ...\tok");
        } catch (Throwable exc) {
            System.err.println("method ...\t" + exc);
        }
        System.err.println();

        try {
            new Main().useSynchronizedBlock();
            System.err.println("block  ...\tok");
        } catch (Throwable exc) {
            System.err.println("block  ...\t" + exc);
        }
        System.err.println();
    }

    void useSynchronizedMethod() {
        System.err.println("before enter\t" + Thread.holdsLock(this));
        internalSynchronizedMethod();
        System.err.println("after  exit\t" + Thread.holdsLock(this));
    }

    private synchronized void internalSynchronizedMethod() {
        System.err.println("after  enter\t" + Thread.holdsLock(this));
        UnsafeMonitor.monitorExit(this);
        System.err.println("before exit\t" + Thread.holdsLock(this));
    }

    void useSynchronizedBlock() {
        System.err.println("before enter\t" + Thread.holdsLock(this));
        synchronized (this) {
            System.err.println("after  enter\t" + Thread.holdsLock(this));
            UnsafeMonitor.monitorExit(this);
            System.err.println("before exit\t" + Thread.holdsLock(this));
        }
        System.err.println("after  exit\t" + Thread.holdsLock(this));
    }

}

// test/UnsafeMonitor.java - it has to be in bootclasspath in order to access Unsafe object.
package test;

import sun.misc.Unsafe;

public class UnsafeMonitor {
    private static final Unsafe unsafe = Unsafe.getUnsafe();

    public static void monitorExit(Object obj) {
        System.err.println("unsafe exit");
        unsafe.monitorExit(obj);
    }

}

The output is following

before enter    false
after  enter    true
unsafe exit
before exit    false
after  exit    false
method ...    ok

before enter    false
after  enter    true
unsafe exit
before exit    false
after  exit    false
block  ...    ok

Regards,
Dmytro

From: davidcholmes at aapt.net.au
To: willmcqueen at yahoo.com; concurrency-interest at cs.oswego.edu
Date: Mon, 14 Dec 2009 18:55:46 +1000
Subject: Re: [concurrency-interest] Are synchronized methods safer than	synchronized blocks?








Hi Will,
 
The issue you raise with synchronized blocks is 
addressed through a somewhat controversial mechanism whereby the catch-all block 
that does the monitorExit acts as its own exception-handler, so if that second 
exception occurs then the monitorExit will be attempted again. This has a 
consequence that if monitorExit itself throws an exception then you tend to 
enter an infinite loop - either continually throwing the exception, or else from 
the second attempt throwing IllegalMonitorStateException because the monitor was 
released prior to the first exception being thrown. But you are at least 
guaranteed not to be able to leave the synchronized block without releasing the 
monitor.
 
See
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4414101
 
and related CRs for some discussion.
 
In relation to use Lock/Condition vs inbuilt. Yes asynchronous exceptions 
can break things.
 
But note that asynchronous exceptions can break just about any Java code. 
So avoiding synchronized blocks and Locks/Conditions to get some perceived 
protection from asynchronous exceptions is misguided and futile. If asynchronous 
exceptions can happen in all but the most trivial of code then you are up the 
proverbial creek without a paddle.
 
Cheers,
David Holmes

  -----Original Message-----
From: 
  concurrency-interest-bounces at cs.oswego.edu 
  [mailto:concurrency-interest-bounces at cs.oswego.edu]On Behalf Of Will 
  McQueen
Sent: Monday, 14 December 2009 6:35 PM
To: 
  concurrency-interest at cs.oswego.edu
Subject: [concurrency-interest] 
  Are synchronized methods safer thansynchronized blocks?


  
    
    
      
        Hi,

Are synchronized methods safer than 
        synchronized blocks, in terms of guaranteeing that any monitors held by 
        a thread will be released before that thread dies?


My 
        understanding is this:

1) The monitor that is acquired when a 
        thread enters a synchronized instance *method* or synchronized static 
        *method* is guaranteed to be released when the method's frame is popped 
        off that thread's stack (provided only that the JVM doesn't crash). That 
        is, the monitor is absolutely guaranteed to be released when the method 
        returns, whether it returned normally, or abnormally (via thrown 
        exception). With synchronized methods, the JVM acquires/releases the 
        monitor on behalf of the thread, since there are no corresponding 
        monitorenter/monitorexit bytecodes for synchronized methods (only for 
        synchronized blocks).

2) A synchronized *block* compiles into 
        Java bytecodes in which a catch-all catch clause (inserted by the 
        compiler) catches any thrown exception (a Throwable?). This 
        compiler-generated catch clause calls 'monitorexit' and then rethrows 
        the exception with 'athrow'.



On p508 of "Inside the Java 
        Virtual Machine, 2nd ed" [Venners], it says "No matter how the 
        synchronized block is exited, the object lock acquired when the thread 
        entered the block will definitely be released". I'm not so sure about 
        that, but I'm hoping to be proven wrong. I believe that using a 
        synchronized block results in a weaker guarantee of releasing a monitor 
        than when using a synchronized method. For example:

Suppose I 
        have an application with 2 threads, T1 and T2. Then suppose:
1) T1 
        enters a synchronized block:
    public static final 
        Object lock = new Object();
    
        ...
    public void foo() {
    
            synchronized(lock) {
    
                ... //T1 is currently executing 
        here
        }
    
        }
    
2) T2 calls foo(), and blocks waiting for T1 
        to exit the monitor associated with the object whose reference is stored 
        in var 'lock'.

3) While T1 is executing within the synchronized 
        block, the JVM causes an Error or RuntimeException to be thrown from T1 
        (or, we can think of some 3rd thread calls Thread.stop on T1, causing a 
        ThreadDeath exception to be thrown from T1... I know Thread.stop is 
        deprecated and unsafe, but I mention it as an analog to what I expect 
        the JVM is doing). This causes execution in T1 to jump to the 
        compiler-generated catch clause to begin execution there. But, just 
        after the catch clause is entered, and before the monitorexit instr is 
        executed, let's say that the JVM causes another Error or 
        RuntimeException to be thrown from T1. So, this 2nd exception would 
        cause immediate exit from the catch clause before the monitorexit instr 
        has executed, correct? The exception continues propagating up the stack 
        until thread T1 dies. In that case, I imagine that T2 would be 
        deadlocked, waiting forever on a monitor that can never be released 
        since the owner is now dead.


If the above is true, then I 
        would conclude that:
1) I should favor synchronized methods over 
        synchronized blocks, especially in critical systems where deadlock must 
        absolutely be avoided.
2) By extension, I should favor synchronized 
        methods over Java 1.5's Lock class (where the Lock object's unlock() 
        method must be called in a finally clause that is also susceptible to 
        the '2nd exception' issue).


Thoughts, comments, and 
        corrections are greatly appreciated.

Thank 
        you.

Cheers,
Will

 		 	   		  
_________________________________________________________________
Windows Live Hotmail: Your friends can get your Facebook updates, right from Hotmail®.
http://www.microsoft.com/middleeast/windows/windowslive/see-it-in-action/social-network-basics.aspx?ocid=PID23461::T:WLMTAGL:ON:WL:en-xm:SI_SB_4:092009
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20091214/c355f368/attachment-0001.html>


More information about the Concurrency-interest mailing list