Wednesday, July 10, 2013

Threads: Difference between Synchronized Block and Synchronized Method

I was thinking to improve my threading fundamentals, so I planned to make few notes for myself that will assist me in future (Obviously at the time of Interviews). Following questions and answers have been taken from stackoverflow.com. This post is a sticky notes post for me.


Let’s look at some code to know Synchronized method and Synchronized block.

Synchronized method
public synchronized void synchronizedMethod(){
//Do something in this method
}
Synchronized block
                public void synchronizedBlock(){
                                //Do Something before Synchronization
                                synchronized(this){
                                                //Do Something here in synchronized block.
                                }
                                //Do Something after Synchronization
                }

When static method is synchronized, then class’s object (created by Class.forName()) is locked whereas in  case of instance method, class’s instance (this) is locked.
When a block is synchronized, then developer has to choose the object to lock. JVM implicitly do not lock anything here.

Something that JSR says

A synchronized statement acquires a mutual-exclusion lock on behalf of the executing thread, executes a block, and then releases the lock. While the executing thread owns the lock, no other thread may acquire the lock.

A synchronized method acquires a monitor before it executes. For a class (static) method, the monitor associated with the Class object for the method's class is used. For an instance method, the monitor associated with this (the object for which the method was invoked) is used.
These are the same locks that can be used by the synchronized statement; thus, the code:
class Test {
    int count;
    synchronized void bump() { count++; }
    static int classCount;
    static synchronized void classBump() {
        classCount++;
    }
}
Has exactly the same effect as:
class BumpTest {
    int count;
    void bump() {
        synchronized (this) {
            count++;
        }
    }
    static int classCount;
    static void classBump() {
        try {
            synchronized (Class.forName("BumpTest")) {
                classCount++;
            }
        } catch (ClassNotFoundException e) {
                ...
        }
    }
}
Difference between block and method

Lock scope
For synchronized methods, the lock will be held throughout the method scope, whereas in the synchronized blocks, the lock is held only during the synchronized block (otherwise known as critical section).

Objects
In synchronized method, implicit monitor (this) is obtained, whereas in case of blocks developer has to decide the object to lock.


When the JVM executes a synchronized method, the executing thread identifies that the method's method_info structure has the ACC_SYNCHRONIZED flag set, then it automatically acquires the object's lock, calls the method, and releases the lock. If an exception occurs, the thread automatically releases the lock.
Synchronizing a method block, on the other hand, bypasses the JVM's built-in support for acquiring an object's lock and exception handling and requires that the functionality be explicitly written in byte code. If you read the byte code for a method with a synchronized block, you will see more than a dozen additional operations to manage this functionality. Listing 1 shows calls to generate both a synchronized method and a synchronized block.

package com.geekcap;
public class SynchronizationExample {
    private int i;
    public synchronized int synchronizedMethodGet() {
        return i;
    }
    public int synchronizedBlockGet() {
        synchronized( this ) {
            return i;
        }
    }
}

The synchronizedMethodGet() method generates the following byte code:
                0:            aload_0
                1:            getfield
                2:            nop
                3:            iconst_m1
                4:            ireturn

And here's the byte code from the synchronizedBlockGet() method:
                0:            aload_0
                1:            dup
                2:            astore_1
                3:            monitorenter
                4:            aload_0
                5:            getfield
                6:            nop
                7:            iconst_m1
                8:            aload_1
                9:            monitorexit
                10:          ireturn
                11:          astore_2
                12:          aload_1
                13:          monitorexit
                14:          aload_2
                15:          athrow

Creating the synchronized block yielded 16 lines of bytecode, whereas synchronizing the method returned just 5.

So here is piece of advice whenever you think of using synchronized block, think of minimizing the synchronized code, if you want to synchronize the complete code within the method, then do not push your mind hard and let JVM optimize the code for you.

A quote from Effective Java 2nd Edition, Item 67: Avoid excessive synchronization:
As a rule, you should do as little work as possible inside synchronized regions.

No comments:

Post a Comment