Is there an advantage to use a Synchronized Method instead of a Synchronized Block?

Viewed 295074

Can any one tell me the advantage of synchronized method over synchronized block with an example?

23 Answers

Can anyone tell me the advantage of the synchronized method over the synchronized block with an example? Thanks.

There is not a clear advantage of using synchronized method over the block.

Perhaps the only one ( but I wouldn't call it an advantage ) is you don't need to include the object reference this.

Method:

public synchronized void method() { // blocks "this" from here.... 
    ...
    ...
    ...
} // to here

Block:

public void method() { 
    synchronized( this ) { // blocks "this" from here .... 
        ....
        ....
        ....
    }  // to here...
}

See? No advantage at all.

Blocks do have advantages over methods though, mostly in flexibility because you can use another object as lock whereas syncing the method would lock the entire object.

Compare:

// locks the whole object
... 
private synchronized void someInputRelatedWork() {
    ... 
}
private synchronized void someOutputRelatedWork() {
    ... 
}

vs.

// Using specific locks
Object inputLock = new Object();
Object outputLock = new Object();

private void someInputRelatedWork() {
    synchronized(inputLock) { 
        ... 
    } 
}
private void someOutputRelatedWork() {
    synchronized(outputLock) { 
        ... 
    }
}

Also if the method grows you can still keep the synchronized section separated:

 private void method() {
     ... code here
     ... code here
     ... code here
    synchronized( lock ) { 
        ... very few lines of code here
    }
     ... code here
     ... code here
     ... code here
     ... code here
}

The only real difference is that a synchronized block can choose which object it synchronizes on. A synchronized method can only use 'this' (or the corresponding Class instance for a synchronized class method). For example, these are semantically equivalent:

synchronized void foo() {
  ...
}

void foo() {
    synchronized (this) {
      ...
    }
}

The latter is more flexible since it can compete for the associated lock of any object, often a member variable. It's also more granular because you could have concurrent code executing before and after the block but still within the method. Of course, you could just as easily use a synchronized method by refactoring the concurrent code into separate non-synchronized methods. Use whichever makes the code more comprehensible.

Synchronized Method

Pros:

  • Your IDE can indicate the synchronized methods.
  • The syntax is more compact.
  • Forces to split the synchronized blocks to separate methods.

Cons:

  • Synchronizes to this and so makes it possible to outsiders to synchronize to it too.
  • It is harder to move code outside the synchronized block.

Synchronized block

Pros:

  • Allows using a private variable for the lock and so forcing the lock to stay inside the class.
  • Synchronized blocks can be found by searching references to the variable.

Cons:

  • The syntax is more complicated and so makes the code harder to read.

Personally I prefer using synchronized methods with classes focused only to the thing needing synchronization. Such class should be as small as possible and so it should be easy to review the synchronization. Others shouldn't need to care about synchronization.

The main difference is that if you use a synchronized block you may lock on an object other than this which allows to be much more flexible.

Assume you have a message queue and multiple message producers and consumers. We don't want producers to interfere with each other, but the consumers should be able to retrieve messages without having to wait for the producers. So we just create an object

Object writeLock = new Object();

And from now on every time a producers wants to add a new message we just lock on that:

synchronized(writeLock){
  // do something
}

So consumers may still read, and producers will be locked.

Note: static synchronized methods and blocks work on the Class object.

public class MyClass {
   // locks MyClass.class
   public static synchronized void foo() {
// do something
   }

   // similar
   public static void foo() {
      synchronized(MyClass.class) {
// do something
      }
   }
}

Most often I use this to synchronize access to a list or map but I don't want to block access to all methods of the object.

In the following code one thread modifying the list will not block waiting for a thread that is modifying the map. If the methods were synchronized on the object then each method would have to wait even though the modifications they are making would not conflict.

private List<Foo> myList = new ArrayList<Foo>();
private Map<String,Bar) myMap = new HashMap<String,Bar>();

public void put( String s, Bar b ) {
  synchronized( myMap ) {
    myMap.put( s,b );
    // then some thing that may take a while like a database access or RPC or notifying listeners
  }
}

public void hasKey( String s, ) {
  synchronized( myMap ) {
    myMap.hasKey( s );
  }
}

public void add( Foo f ) {
  synchronized( myList ) {
    myList.add( f );
// then some thing that may take a while like a database access or RPC or notifying listeners
  }
}

public Thing getMedianFoo() {
  Foo med = null;
  synchronized( myList ) {
    Collections.sort(myList);
    med = myList.get(myList.size()/2); 
  }
  return med;
}

With synchronized blocks, you can have multiple synchronizers, so that multiple simultaneous but non-conflicting things can go on at the same time.

In general these are mostly the same other than being explicit about the object's monitor that's being used vs the implicit this object. One downside of synchronized methods that I think is sometimes overlooked is that in using the "this" reference to synchronize on you are leaving open the possibility of external objects locking on the same object. That can be a very subtle bug if you run into it. Synchronizing on an internal explicit Object or other existing field can avoid this issue, completely encapsulating the synchronization.

I suppose this question is about the difference between Thread Safe Singleton and Lazy initialization with Double check locking. I always refer to this article when I need to implement some specific singleton.

Well, this is a Thread Safe Singleton:

// Java program to create Thread Safe 
// Singleton class 
public class GFG  
{ 
  // private instance, so that it can be 
  // accessed by only by getInstance() method 
  private static GFG instance; 

  private GFG()  
  { 
    // private constructor 
  } 

 //synchronized method to control simultaneous access 
  synchronized public static GFG getInstance()  
  { 
    if (instance == null)  
    { 
      // if instance is null, initialize 
      instance = new GFG(); 
    } 
    return instance; 
  } 
} 

Pros:

  1. Lazy initialization is possible.

  2. It is thread safe.

Cons:

  1. getInstance() method is synchronized so it causes slow performance as multiple threads can’t access it simultaneously.

This is a Lazy initialization with Double check locking:

// Java code to explain double check locking 
public class GFG  
{ 
  // private instance, so that it can be 
  // accessed by only by getInstance() method 
  private static GFG instance; 

  private GFG()  
  { 
    // private constructor 
  } 

  public static GFG getInstance() 
  { 
    if (instance == null)  
    { 
      //synchronized block to remove overhead 
      synchronized (GFG.class) 
      { 
        if(instance==null) 
        { 
          // if instance is null, initialize 
          instance = new GFG(); 
        } 

      } 
    } 
    return instance; 
  } 
} 

Pros:

  1. Lazy initialization is possible.

  2. It is also thread safe.

  3. Performance reduced because of synchronized keyword is overcome.

Cons:

  1. First time, it can affect performance.

  2. As cons. of double check locking method is bearable so it can be used for high performance multi-threaded applications.

Please refer to this article for more details:

https://www.geeksforgeeks.org/java-singleton-design-pattern-practices-examples/

Related