Java Synchronized Block
In my earlier post, we learned about the Java synchronized method. In this post, let’s learn about the synchronized block.
Join the DZone community and get the full member experience.
Join For FreeIn my earlier post, we learned about the Java synchronized method. In this post, let’s learn about the synchronized block.
Video: To see the visual walk-through of this post, click below:
What Is Synchronized Block?
The synchronized block is used to prevent multiple threads from executing a portion of a code in a method at the same point in time. On the other hand, the synchronized method will prevent multiple threads from executing the entire method at the same point in time.
Synchronized Block Example
In our earlier post, we explained the synchronized method through the BoyFriend
threads and the GirlFriend
example program. Now, let’s rewrite the same example program using the synchronized block approach.
01: public class SynchronizationBlockDemo {
02:
03: private static class BoyFriendThread extends Thread {
04:
05: @Override
06: public void run() {
07:
08: girlFriend.meet();
09: }
10: }
11:
12: private static GirlFriend girlFriend = new GirlFriend();
13:
14: public static void main(String[] args) {
15:
16: for (int counter = 0; counter < 10; ++counter) {
17:
18: BoyFriendThread fThread = new BoyFriendThread();
19: fThread.setName("BoyFriend-" + counter);
20: fThread.start();
21: }
22: }
23: }
Note: we haven’t made any changes to how we are launching the BoyFriend
threads. It remains as is. However, we have modified the GirlFriend
class to use the synchronized block as shown below:
01: public class GirlFriend {
02:
03: private Object assistant = new Object();
04:
05: public void meet() {
06:
07: synchronized (assistant) {
08:
09: try {
10:
11: String threadName = Thread.currentThread().getName();
12: System.out.println(threadName + " meeting started!");
13: Thread.sleep(100);
14: System.out.println(threadName + " meeting ended!!");
15: } catch (Exception e) {
16: }
17: }
18: }
19: }
If you notice, in the GirlFriend
class, we have introduced a new object, the assistant
in line #3. Instead of making the entire meet()
method as synchronized, we have now introduced synchronized (assistant) {
in line #7. This synchronized block ends on line #17, and it will prevent multiple threads from executing these lines of code. Only one thread will be allowed to execute the code from line #8 to #17 at any given time. When we executed the above program, below is the output we got:
BoyFriend-0 meeting started!
BoyFriend-0 meeting ended!!
BoyFriend-9 meeting started!
BoyFriend-9 meeting ended!!
BoyFriend-8 meeting started!
BoyFriend-8 meeting ended!!
BoyFriend-7 meeting started!
BoyFriend-7 meeting ended!!
BoyFriend-6 meeting started!
BoyFriend-6 meeting ended!!
BoyFriend-5 meeting started!
BoyFriend-5 meeting ended!!
BoyFriend-4 meeting started!
BoyFriend-4 meeting ended!!
BoyFriend-3 meeting started!
BoyFriend-3 meeting ended!!
BoyFriend-2 meeting started!
BoyFriend-2 meeting ended!!
BoyFriend-1 meeting started!
BoyFriend-1 meeting ended!!
How Do Synchronized Blocks Work in Java?
JVM will allow only one thread to enter into a synchronized block code at a given point in time. When a thread enters a synchronized block, it acquires the lock of the object on which it’s synchronized. In the above example, it’s the assistant
object. Only after this thread releases the lock will other threads be allowed to enter the synchronized block of the code. Say the BoyFriend-0
thread is executing the synchronized block of the code. Only after this thread exits the block will other threads be allowed to enter the synchronized block of code. Until then, all other threads which are trying to invoke the synchronized block of code will be put into the BLOCKED thread state.
Threads Behavior of a Synchronized Block
To confirm this theory, we executed the above program and captured the thread dump using the open-source script yCrash. We analyzed the thread dump using the fastThread tool. Here is the generated thread dump analysis report of this simple program. Below is the excerpt from the thread dump analysis report:
Fig 1: fastThread tool reporting 9 threads are in BLOCKED state
Fig 2: fastThread tool reporting 9 threads to be in BLOCKED state when accessing assistant Object
fastThread tool reports the total number of blocked threads and a transitive graph showing where they are BLOCKED. In this example (Fig 1), the tool reported that 9 threads are in BLOCKED state. From the transitive graph (Fig 2), you can notice that the BoyFriend1
is blocking the remaining 9 BoyFriend
threads. When clicking on the thread names, you can see its complete stack trace. Below is the stack trace of one of the BoyFriend
threads which is BLOCKED:
01: java.lang.Thread.State: BLOCKED (on object monitor)
02: at learn.synchblock.GirlFriend.meet(GirlFriend.java:13)
03: - waiting to lock <0x00000007141e4330> (a java.lang.Object)
04: at learn.synchblock.SynchronizationBlockDemo$BoyFriendThread.run(SynchronizationBlockDemo.java:10)
05: Locked ownable synchronizers:
06: - None
The above stack trace is very similar to the BLOCKED BoyFriend
thread stack trace in the synchronized method example. However, there is only one difference. In line #3, this BoyFriend
thread is waiting to acquire the lock of the java.lang.Object
(i.e. assistant
), whereas in the synchronized method example, the BoyFriend thread was waiting to acquire the lock of the GirlFriend
object. Below is the stack trace of the BLOCKED BoyFriend
thread in the synchronized method example:
01: java.lang.Thread.State: BLOCKED (on object monitor)
02: at learn.synchornized.GirlFriend.meet(GirlFriend.java:7)
03: - waiting to lock <0x0000000714173850> (a learn.synchornized.GirlFriend)
04: at learn.synchornized.SynchronizationDemo$BoyFriendThread.run(SynchronizationDemo.java:10)
05: Locked ownable synchronizers:
06: - None
Advantages of Synchronized Block Over Synchronized Method
Synchronized block has the following advantages when compared to the synchronized method:
A. Synchronize Only Portion of Method
When you use a synchronized method, the entire code in that method will be synchronized. Say, suppose you want to synchronize only a portion of code in the method. You can’t use the synchronized method. In that circumstance, you need to use a synchronized block.
B. Synchronize on Any Object
When you use a synchronized method, you can’t use any other object other than the underlying object (in the case of a static synchronized method, it would be the underlying class) of that method for synchronization. On the other hand, when you use a synchronized block, you can use any object. In the above example, we are using an ‘assistant’ object for synchronization (Which is totally different from the GirlFriend object in which this method was present).
C. Change Synchronizing Objects Based on Certain Conditions
You can change the objects on which you are synchronizing dynamically. Look at the below example:
01: public void doSomething(Object myLock) {
02:
03: :
04: :
05: synchronize (myLock) {
06:
07: // code to be synchronized
08: }
09: :
10: :
11: }
Here, we are synchronizing the myLock
object. However, the myLock
can have different objects based on the invoker of the doSomething()
method. Maybe, for each customer, we can pass different myLock objects. This is not achievable with synchronized methods.
Disadvantages of Synchronized Block Over Synchronized Method
Synchronized block has the following disadvantages when compared to the synchronized method:
Clean Code
Code readability is better with the synchronized method over the synchronized block. In the synchronized method scenario, it’s enough if you can just insert the synchronized
keyword in the method declaration, whereas in the synchronized block, you need to do several additional things. Below is the code of a synchronized method and synchronized block:
Fig: Synchronized Block
You can notice that in the synchronized block, you need to do the following additional steps:
- Declare the synchronizing object
- Write one extra line of code on the synchronizing object
- Code to be synchronized needs to be given one more extra level of tab
- Need to put one extra opening brace and closing brace
It clutters your code when compared to synchronized methods.
Safe Code
Synchronized methods might be safer to write than synchronized blocks for the following two reasons:
a) NullPointerException
In a synchronized block, you synchronize the code block on a new object. At runtime, the synchronizing object can turn out to be null. In those circumstances, you will end up getting a NullPointerException.
b) Synchronizing on unsafe objects
There are certain objects which are risky to synchronize. Example: Strings and Boxed Objects (Integer, Float, Double,…). Because these objects are deduplicated by the JVM at runtime for optimal performance. In such circumstances, synchronized blocks will not work properly, and it will lead to nasty bugs in your application.
Published at DZone with permission of Ram Lakshmanan, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments