Why is synchronized block better than synchronized method?

JavaMultithreadingSynchronization

Java Problem Overview


I have started learning synchronization in threading.

Synchronized method:

public class Counter {

   private static int count = 0;

   public static synchronized int getCount() {
      return count;
   }

   public synchronized setCount(int count) {
      this.count = count;
   }

}

Synchronized block:

public class Singleton {

   private static volatile Singleton _instance;

   public static Singleton getInstance() {
      if (_instance == null) {
         synchronized(Singleton.class) {
            if (_instance == null)
               _instance = new Singleton();
         }
      }
      return _instance;
   }
}

When should I use synchronized method and synchronized block?

Why is synchronized block better than synchronized method ?

Java Solutions


Solution 1 - Java

It's not a matter of better, just different.

When you synchronize a method, you are effectively synchronizing to the object itself. In the case of a static method, you're synchronizing to the class of the object. So the following two pieces of code execute the same way:

public synchronized int getCount() {
    // ...
}

This is just like you wrote this.

public int getCount() {
    synchronized (this) {
        // ...
    }
}

If you want to control synchronization to a specific object, or you only want part of a method to be synchronized to the object, then specify a synchronized block. If you use the synchronized keyword on the method declaration, it will synchronize the whole method to the object or class.

Solution 2 - Java

Although not usually a concern, from a security perspective, it is better to use synchronized on a private object, rather than putting it on a method.

Putting it on the method means you are using the lock of the object itself to provide thread safety. With this kind of mechanism, it is possible for a malicious user of your code to also obtain the lock on your object, and hold it forever, effectively blocking other threads. A non-malicious user can effectively do the same thing inadvertently.

If you use the lock of a private data member, you can prevent this, since it is impossible for a malicious user to obtain the lock on your private object.

private final Object lockObject = new Object();

public void getCount() {
    synchronized( lockObject ) {
        ...
    }
}

This technique is mentioned in Bloch's Effective Java (2nd Ed), Item #70

Solution 3 - Java

The difference is in which lock is being acquired:

  • synchronized method acquires a lock on the whole object. This means no other thread can use any synchronized method in the whole object while the method is being run by one thread.

  • synchronized blocks acquires a lock in the object between parentheses after the synchronized keyword. Meaning no other thread can acquire a lock on the locked object until the synchronized block exits.

So if you want to lock the whole object, use a synchronized method. If you want to keep other parts of the object accessible to other threads, use synchronized block.

If you choose the locked object carefully, synchronized blocks will lead to less contention, because the whole object/class is not blocked.

This applies similarly to static methods: a synchronized static method will acquire a lock in the whole class object, while a synchronized block inside a static method will acquire a lock in the object between parentheses.

Solution 4 - Java

Difference between synchronized block and synchronized method are following:

  1. synchronized block reduce scope of lock, but synchronized method's scope of lock is whole method.
  2. synchronized block has better performance as only the critical section is locked but synchronized method has poor performance than block.
  3. synchronized block provide granular control over lock but synchronized method lock either on current object represented by this or class level lock.
  4. synchronized block can throw NullPointerException but synchronized method doesn't throw.
  5. synchronized block: synchronized(this){}

synchronized method: public synchronized void fun(){}

Solution 5 - Java

Define 'better'. A synchronized block is only better because it allows you to:

  1. Synchronize on a different object
  2. Limit the scope of synchronization

Now your specific example is an example of the double-checked locking pattern which is suspect (in older Java versions it was broken, and it is easy to do it wrong).

If your initialization is cheap, it might be better to initialize immediately with a final field, and not on the first request, it would also remove the need for synchronization.

Solution 6 - Java

synchronized should only be used when you want your class to be Thread safe. In fact most of the classes should not use synchronized anyways. synchronized method would only provide a lock on this object and only for the duration of its execution. if you really wanna to make your classes thread safe, you should consider making your variables volatile or synchronize the access.

one of the issues of using synchronized method is that all of the members of the class would use the same lock which will make your program slower. In your case synchronized method and block would execute no different. what I'd would recommend is to use a dedicated lock and use a synchronized block something like this.

public class AClass {
private int x;
private final Object lock = new Object();     //it must be final!

 public void setX() {
    synchronized(lock) {
        x++;
    }
 }
}

Solution 7 - Java

In your case both are equivalent!

Synchronizing a static method is equivalent to a synchronized block on corresponding Class object.

In fact when you declare a synchronized static method lock is obtained on the monitor corresponding to the Class object.

public static synchronized int getCount() {
    // ...
}

is same as

public int getCount() {
    synchronized (ClassName.class) {
        // ...
    }
}

Solution 8 - Java

One classic difference between Synchronized block and Synchronized method is that Synchronized method locks the entire object. Synchronized block just locks the code within the block.

Synchronized method: Basically these 2 sync methods disable multithreading. So one thread completes the method1() and the another thread waits for the Thread1 completion.

class SyncExerciseWithSyncMethod {

    public synchronized void method1() {
        try {
            System.out.println("In Method 1");
            Thread.sleep(5000);
        } catch (Exception e) {
            System.out.println("Catch of method 1");
        } finally {
            System.out.println("Finally of method 1");
        }

    }

    public synchronized void method2() {
        try {
            for (int i = 1; i < 10; i++) {
                System.out.println("Method 2 " + i);
                Thread.sleep(1000);
            }
        } catch (Exception e) {
            System.out.println("Catch of method 2");
        } finally {
            System.out.println("Finally of method 2");
        }
    }
}
Output
-------

In Method 1

Finally of method 1

Method 2 1

Method 2 2

Method 2 3

Method 2 4

Method 2 5

Method 2 6

Method 2 7

Method 2 8

Method 2 9

Finally of method 2

Synchronized block: Enables multiple threads to access the same object at same time [Enables multi-threading].

class SyncExerciseWithSyncBlock {

    public Object lock1 = new Object();
    public Object lock2 = new Object();

    public void method1() {
        synchronized (lock1) {
            try {
                System.out.println("In Method 1");
                Thread.sleep(5000);
            } catch (Exception e) {
                System.out.println("Catch of method 1");
            } finally {
                System.out.println("Finally of method 1");
            }
        }

    }

    public void method2() {

        synchronized (lock2) {
            try {
                for (int i = 1; i < 10; i++) {
                    System.out.println("Method 2 " + i);
                    Thread.sleep(1000);
                }
            } catch (Exception e) {
                System.out.println("Catch of method 2");
            } finally {
                System.out.println("Finally of method 2");
            }
        }
    }

}

Output
-------
In Method 1

Method 2 1

Method 2 2

Method 2 3

Method 2 4

Method 2 5

Finally of method 1

Method 2 6

Method 2 7

Method 2 8

Method 2 9

Finally of method 2

Solution 9 - Java

Because lock is expensive, when you are using synchronized block you lock only if _instance == null, and after _instance finally initialized you'll never lock. But when you synchronize on method you lock unconditionally, even after the _instance is initialized. This is the idea behind double-checked locking optimization pattern http://en.wikipedia.org/wiki/Double-checked_locking.

Solution 10 - Java

It should not be considered as a question of best for usage, but it really depends on the use case or the scenario.

Synchronized Methods

An entire method can be marked as synchronized resulting an implicit lock on the this reference (instance methods) or class (static methods). This is very convenient mechanism to achieve synchronization.

Steps A thread access the synchronized method. It implicitly acquires the lock and execute the code. If other thread want to access the above method, it has to wait. The thread can't get the lock, will be blocked and has to wait till the lock is released.

Synchronized Blocks

To acquire a lock on an object for a specific set of code block, synchronized blocks are the best fit. As a block is sufficient, using a synchronized method will be a waste.

More specifically with Synchronized Block , it is possible to define the object reference on which are want to acquire a lock.

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
QuestionSabapathyView Question on Stackoverflow
Solution 1 - JavaErick RobertsonView Answer on Stackoverflow
Solution 2 - JavawolfcastleView Answer on Stackoverflow
Solution 3 - JavaAngular UniversityView Answer on Stackoverflow
Solution 4 - JavaRaman GuptaView Answer on Stackoverflow
Solution 5 - JavaMark RotteveelView Answer on Stackoverflow
Solution 6 - JavaAshishView Answer on Stackoverflow
Solution 7 - JavaAniket ThakurView Answer on Stackoverflow
Solution 8 - JavaSriView Answer on Stackoverflow
Solution 9 - JavaEvgeniy DorofeevView Answer on Stackoverflow
Solution 10 - JavaSameeraView Answer on Stackoverflow