When a method is synchronized, only one thread can enter that object’s method at a given point in time. If any other thread tries to enter the synchronized method, it will NOT be allowed to enter. It will be put in the BLOCKED state.
In this post, let’s learn a little more details about synchronized method.
Video: To see the visual walk-through of this post, click below:
https://youtu.be/PJtxT3cgCPk
Java Synchronized method example
It’s always easy to learn with an example. Here is an interesting program that I have put together which facilitate us to understand synchronized method behavior better:
01: public class SynchronizationDemo { 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: }In this program, there are two classes:01: public class GirlFriend { 02: 03: public void meet() { 04: 05: String threadName = Thread.currentThread().getName(); 06: System.out.println(threadName + " meeting started!"); 07: System.out.println(threadName + " meeting ended!!"); 08: } 09: }
1. SynchronizationDemo: In this class, you can notice that we are starting 10 BoyFriendThread from line #18 – #20. Each ‘BoyFriendThread’ is invoking ‘meet()’ method on the ‘GirlFriend’ object in (line #8).
2. GirlFriend: In this class, there is only one method ‘meet()’. This method prints the name of the ‘Boyfriend’ thread name and “meeting started!” and “meeting stopped!!”
When the ‘SynchronizationDemo’ program is executed, it prints following as the output:
You can notice that ‘…meeting started!‘ and ‘…meeting stopped!!‘ statements of each thread are not printed consecutively. Example, on line #1 meeting with BoyFriend-0 started, while that meeting is in progress, meetings with ‘BoyFriend-8’ (line #2) and ‘BoyFriend-1’ (line #3) also started. Only after that, the meeting with ‘BoyFriend-0’ ends. This kind of mixed meetings continue all throughout the program. If this happens in the real world, then our ‘GirlFriend’ object will be in trouble. We should save her from this trouble. Only after her meeting with one boyfriend completes, the next meeting should resume. This is where ‘synchronization’ comes to help.01: BoyFriend-0 meeting started! 02: BoyFriend-8 meeting started! 03: BoyFriend-1 meeting started! 04: BoyFriend-0 meeting ended!! 05: BoyFriend-4 meeting started! 06: BoyFriend-3 meeting started! 07: BoyFriend-3 meeting ended!! 08: BoyFriend-2 meeting started! 09: BoyFriend-8 meeting ended!! 10: BoyFriend-2 meeting ended!! 11: BoyFriend-5 meeting started! 12: BoyFriend-6 meeting started! 13: BoyFriend-6 meeting ended!! 14: BoyFriend-7 meeting started! 15: BoyFriend-7 meeting ended!! 16: BoyFriend-9 meeting started! 17: BoyFriend-1 meeting ended!! 18: BoyFriend-4 meeting ended!! 19: BoyFriend-9 meeting ended!! 20: BoyFriend-5 meeting ended!!
Let’s change the ‘meet()’ method in the ‘GirlFriend’ object to be synchronized and execute the program once again.
Notice that in line #3, the synchronized keyword is introduced in the ‘meet()’ method. When we executed the same program once again, below is the result we got:01: public class GirlFriend { 02: 03: public synchronized void meet() { 04: 05: String threadName = Thread.currentThread().getName(); 06: System.out.println(threadName + " meeting started!"); 07: System.out.println(threadName + " meeting ended!!"); 08: } 09: }
Bingo!! Now you can see each meeting with a boyfriend started and ended sequentially. Only after completing a meeting with ‘BoyFriend-0’, a meeting with ‘BoyFriend-5’ starts. This should make the ‘GirlFriend’ object quite happy, as she can focus on one Boyfriend at a time.01: BoyFriend-2 meeting started! 02: BoyFriend-2 meeting ended!! 03: BoyFriend-0 meeting started! 04: BoyFriend-0 meeting ended!! 05: BoyFriend-5 meeting started! 06: BoyFriend-5 meeting ended!! 07: BoyFriend-8 meeting started! 08: BoyFriend-8 meeting ended!! 09: BoyFriend-9 meeting started! 10: BoyFriend-9 meeting ended!! 11: BoyFriend-6 meeting started! 12: BoyFriend-6 meeting ended!! 13: BoyFriend-7 meeting started! 14: BoyFriend-7 meeting ended!! 15: BoyFriend-4 meeting started! 16: BoyFriend-4 meeting ended!! 17: BoyFriend-3 meeting started! 18: BoyFriend-3 meeting ended!! 19: BoyFriend-1 meeting started! 20: BoyFriend-1 meeting ended!!
Note: Some of you might wonder why BoyFriend threads are not meeting the ‘GirlFriend’ object in sequential order. I.e. one would expect to see ‘BoyFriend-0’ meeting to complete first and then ‘BoyFriend-0’ meeting and then ‘’ meeting.. But instead now meetings are not held in sequential order. To find answer to this question please see this Java Fairness post.
How does the Synchronized method work in Java?
When you make a method synchronized, only one thread will be allowed to execute that method at a given point in time. When a thread enters a synchronized method, it acquires the lock of the object. Only after this thread releases the lock, other threads will be allowed to enter the synchronized method. Say if ‘BoyFriend-0’ thread is executing the ‘meet()’ method, only after this thread exits the method, other threads will be allowed to enter the ‘meet()’ method, until then all other threads which are trying to invoke the ‘meet()’ method will be put to BLOCKED thread state.
Threads behavior when a method is Synchronized
To confirm this theory, we executed the above program and captured thread dump using 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 GirlFriend Object
fastThread tool reports the total number of blocked threads and a transitive graph to indicate where they areBLOCKED. 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 ‘BoyFriend2’ 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:
You can see that this ‘BoyFriend’ thread is put in to BLOCKED state when it’s trying to execute the ‘meet()’ method (as reported in line #2).1: 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$BoyFriendTh read.run(SynchronizationDemo.java:10) 05: Locked ownable synchronizers: 06: - None
Conclusion
In this post, we learnt about the basics of the ‘synchronized’ method. If you want to learn more details about ‘synchronized’ method you may refer here