In this post, we will see Synchronization in Java with example. Let’s see some basic points about synchronization in Thread.
- Synchronization is a process that allows thread execution one by one to prevent more than one thread to access a resource(object)simultaneously.
- For the Synchronization process, we need to use the Synchronized keyword.
- We can use the synchronized keyword with a method or block only(can’t use with classes, interfaces, enum or variables).
Why we need Synchronization in multithreading – Suppose there are multiple threads that trying to access the same resource(object) at the same time. In this case, if one thread performs some task on that resource and another thread performs some different task then we may have data inconsistent problem in the final result.
If we use a synchronized method or block then at a time only one thread is allowed to access the resource(object). The benefit of Synchronization is it resolves data inconsistency problem but sometimes Synchronization leads performance issue since one thread wait for another thread.
How Synchronization works internally – Synchronization works on the locking concept. Whenever we create an object in java there is a lock available for that object but it only comes in effect when we use a synchronized method or block code. There is only one lock per object. When we enter a synchronized instance method, we automatically acquire the lock associated with the current object of the class whose code we’re executing (this instance). Acquiring a lock for an object is also known as getting the lock or locking the object. Since there is only one lock per object, if one thread has picked up the lock, no other thread can pick up the lock until the first thread releases the lock. This means no other thread can enter the synchronized code until the lock has been released. Releasing a lock means the thread holding the lock (in other words, the thread currently in the synchronized method) exits the synchronized method. Once method execution completes automatically thread will release the lock. Acquiring and releasing the lock managed by JVM.
In the above diagram, while a thread(t1) executing a synchronized method on the given resource(Object) the remaining threads(t2,t3,t4) not allowed to execute that synchronized method simultaneously(they will wait for lock).
Java Synchronization Example –
Let’s see an example of where we will create multiple threads(two thread) and one resource(object).
Example without synchronization –
package synchronization; class Hello { public void sayHello(String name) { for (int i = 0; i < 5; i++) { System.out.println("Hello:- " + name); } } } class CustomThread extends Thread { Hello hello; String name; public CustomThread(Hello hello, String name) { super(); this.hello = hello; this.name = name; } public void run() { hello.sayHello(name); } } public class Example1 { public static void main(String[] args) { Hello hello = new Hello(); CustomThread t1 = new CustomThread(hello, "ram"); CustomThread t2 = new CustomThread(hello, "mohan"); t1.start(); t2.start(); } }
In the above program, we have created two threads(to keep program simple we have only two threads) and one resource (object). Line 30 and 31 we have created two threads t1 and t2 and line 29 we have created a resource/object i.e hello. Thread t1 and t2 will access resource hello simultaneously.
Let’s observe the output.
Output is (it may vary because it depends on thread scheduler) –
Hello:- ram
Hello:- mohan
Hello:- ram
Hello:- mohan
Hello:- ram
Hello:- mohan
Hello:- ram
Hello:- mohan
Hello:- ram
Hello:- mohan
In the above output, we have mixed out which is expected because both threads t1 and t2 accessing hello object same time. Let’s modify the program as below, use synchronized keyword with sayHello() method.
package synchronization; class Hello { public synchronized void sayHello(String name) { for (int i = 0; i < 5; i++) { System.out.println("Hello:- " + name); } } } class CustomThread extends Thread { Hello hello; String name; public CustomThread(Hello hello, String name) { super(); this.hello = hello; this.name = name; } public void run() { hello.sayHello(name); } } public class Example1 { public static void main(String[] args) { Hello hello = new Hello(); CustomThread t1 = new CustomThread(hello, "ram"); CustomThread t2 = new CustomThread(hello, "mohan"); t1.start(); t2.start(); } }
Output is –
Hello:- ram
Hello:- ram
Hello:- ram
Hello:- ram
Hello:- ram
Hello:- mohan
Hello:- mohan
Hello:- mohan
Hello:- mohan
Hello:- mohan
or
Hello:- mohan
Hello:- mohan
Hello:- mohan
Hello:- mohan
Hello:- mohan
Hello:- ram
Hello:- ram
Hello:- ram
Hello:- ram
Hello:- ram
[stextbox id=’info’]Now thread t1 and t2 will execute one by one. We will not have a mixed output. Since we have used synchronized keyword with sayHello() method as soon as run() method will get invoked using start() method further sayHello() method will get called and since it is synchronized, whoever thread is going to call sayHello() method will acquire the lock. Although it totally depends on JVM which thread will get a lock first, for now just assume t1 get the lock first, now t2 will wait until t1 will complete his task(as of now his task is to print Hello:- ram five times). Once t1 completed his task it will release the lock and t2 will get the lock.[/stextbox]
Synchronization can be implemented in three ways –
- Using synchronized method
- Using synchronized block
- Static synchronization
Using synchronized method – We have already seen an example of how to use synchronized keyword with method.
Using synchronized block – Let’s see how to use the synchronized keyword as a block.
Syntax:-
public void sayHello(String name) { synchronized (this) { //some logic } }
Example of a synchronized block – We will use the same example that has been used for the synchronized method only changes we will have instead of the synchronized method we will have synchronized block.
package synchronization; class Hello { public void sayHello(String name) { synchronized (this) { for (int i = 0; i < 5; i++) { System.out.println("Hello:- " + name); } } } } class CustomThread extends Thread { Hello hello; String name; public CustomThread(Hello hello, String name) { super(); this.hello = hello; this.name = name; } public void run() { hello.sayHello(name); } } public class Example1 { public static void main(String[] args) { Hello hello = new Hello(); CustomThread t1 = new CustomThread(hello, "ram"); CustomThread t2 = new CustomThread(hello, "mohan"); t1.start(); t2.start(); } }
Output is –
Hello:- mohan
Hello:- mohan
Hello:- mohan
Hello:- mohan
Hello:- mohan
Hello:- ram
Hello:- ram
Hello:- ram
Hello:- ram
Hello:- ram
or
Hello:- ram
Hello:- ram
Hello:- ram
Hello:- ram
Hello:- ram
Hello:- mohan
Hello:- mohan
Hello:- mohan
Hello:- mohan
Hello:- mohan
In the above program at line 5, we are using a synchronized block and passing this as the parameter. For beginners, it may be confusing what “this” doing here. It refers to the current class object as it always does.
Static synchronization –
In the case of static synchronized method it will lock the class instead of the object since static belongs to class level. Static synchronized means Only one thread can access the class at one time.
That’s all about Synchronization In Java With Example.
You may like.
- Runnable interface in java.
- Daemon thread in java with example.
- Thread Priority in Java with example.
- Thread sleep() method in Java.
- Thread join() method in Java.
- Thread yield() method in Java with Example.
- Thread getId() method in Java.
- Thread getName() method in java.
- Thread dumpStack() method in Java.
- Thread currentThread() method in Java.
- Thread checkAccess() method in Java.
- Thread activeCount() method in Java.
- Thread life cycle in Java.
See docs here.