Multi-threaded programs may regularly come up with a circumstance where multiple Java threads attempt to get to the same resource which produces fraudulent and startling outcomes. This can be solved by using the synchronization in Java. Just a single specific thread can get to the resource at a given purpose of time. This article will help you to become familiar with the synchronization strategy.
I’ll be discussing the topics in this order:
- Why use Synchronization in Java?
- Types of Synchronization
- Locks in Java
- Multi-threading without Synchronization
- Multi-threading with Synchronization
- Synchronized Keyword
- Difference between synchronized keyword and synchronized block
Let’s get started!
Why use Synchronization in Java?
If you start with at least two threads inside a program, there might be a chance when multiple threads attempt to get to the same resource. It can even create an unexpected outcome because of concurrency issues.
Syntax:
synchronized(objectidentifier) { // Access shared variables and other shared resources; }
For example, multiple threads attempt to write within an equivalent file. This may corrupt the data since one of the threads can override the data or when a thread is opening the same file at the same time, another thread might be closing the same file. There is a need to synchronize the action of multiple threads. This can be implemented using a concept called Monitors.
- Each object in Java is associated with a monitor, which a thread can lock or unlock.
- Only one thread at a time may hold a lock on a monitor.
- Java programming language provides a very handy way of creating threads and synchronizing their task by using the Synchronized blocks.
- It also keeps the shared resources within this particular block.
Synchronized blocks in Java are marked with the Synchronized keyword. This block in Java is synchronized on some object. All blocks that are synchronized on the same object can only have one thread executing inside them at a time. All other threads attempting to enter the synchronized block are blocked until the thread inside the synchronized block exits the block.
Types of Synchronization
There are basically two types of synchronization available. They are:
- Process Synchronization: The simultaneous execution of multiple threads or processes to reach a state such that they commit to a certain sequence of actions.
- Thread Synchronization: At times when more than one thread tries to access a shared resource, you need to ensure that resource will be used by only one thread at a time.
Let’s not get into the details of these types and try to understand what are locks in Java.
Locks in Java
As I mentioned earlier, Synchronization is built around an internal entity known as the lock or monitor. Each and every object has a lock associated with it. So a thread that needs consistent access to an object’s fields needs to acquire the object’s lock before accessing them, and then release the lock when the work is done.
From Java 5, the package java.util.concurrent.locks contains many lock implementations.
This is how a lock looks like:
public class Lock { private boolean isLocked = false; public synchronized void lock() throws InterruptedException { while(isLocked) { wait(); } isLocked = true; } public synchronized void unlock() { isLocked = false; notify(); } }
The lock() method locks the Lock instance so that all threads calling lock() are blocked until unlock() is executed.
Multi-threading without Synchronization
Here is a simple example which prints the counter value in a sequence and every time we run it, it produces a different result based on CPU availability to a thread. Check this out!
class Multithread { public void printCount() { try { for(int i = 5; i<0; i--) { System.out.println("Counter --- " + i ); } } catch (Exception e) { System.out.println("Thread interrupted."); } } } class Thread extends Multithread { private Thread t; private String threadName; Multithread MT; Thread( String name, Multithread mt) { threadName = name; MT= mt; } public void run() { MT.printCount(); System.out.println("Thread " + threadName + " exiting."); } public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { Multithread MT = new Multithread(); Thread t = new Thread( "Thread - 1 ", MT); Thread t1 = new Thread( "Thread - 2 ", MT); t.start(); t1.start(); // wait for threads to end try { t.join(); t1.join(); } catch ( Exception e) { System.out.println("Interrupted"); } } }
The above program’s results in this:
Multi-threading with Synchronization
This is the same example as above but it prints the counter value in the sequence. Every time we run it, it produces the same result.
class Multithread { public void printCount() { try { for(int i = 5; i > 0; i--) { System.out.println("Counter --- " + i ); } } catch (Exception e) { System.out.println("Thread interrupted."); } } } class Thread extends Multithread { private Thread t; private String threadName; Multithread MT; Thread( String name, Multithread mt) { threadName = name; MT= mt; } public void run() { synchronized(MT) { MT.printCount(); } System.out.println("Thread " + threadName + " exiting."); } public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { Multithread MT = new Multithread(); Thread T = new Thread( "Thread - 1 ", MT); Thread T1 = new Thread( "Thread - 2 ", MT); T.start(); T1.start(); // wait for threads to end try { T.join(); T1.join(); } catch ( Exception e) { System.out.println("Interrupted"); } } }
The output is depicted below:
Synchronized Keyword
Java synchronized keyword marks a block or a method a critical section. A critical section is where only one thread is executing at a time, and the thread holds the lock for the synchronized section. This synchronized keyword helps in writing concurrent parts of any application. It also protects shared resources within the block.
The synchronized keyword can be used with:
Synchronized Keyword: A code block
Syntax
The general syntax for writing a synchronized block is:
synchronized ( lockObject) { //synchronized statements }
When a thread wants to execute the synchronized statements inside the block, it must acquire the lock on the lockObject‘s monitor. Only one thread can acquire the monitor of a lock object at a time. So all other threads must wait till the currently executing thread acquires the lock and finish its execution.
This way, the synchronized keyword guarantees that only one thread will be executing the synchronized block statements at a time, and thus prevents multiple threads from corrupting the shared data that is present inside the block.
Note:
- If a thread is put on sleep (using
sleep()
method) then it does not release the lock. During this sleep time, no thread will be executing the synchronized block statements. - Java synchronization will throw NullPointerException if lock object used in ‘synchronized (lock)‘ is null.
Now, let’s discuss the method.
Synchronized Keyword: A method
Syntax
The general syntax for writing a synchronized method is:
<access modifier> synchronized method ( parameters) { //synchronized code }
Here lockObject is just a reference to an object whose lock is associated with the monitor which represents the synchronized statements.
Similar to the synchronized block, a thread must acquire the lock on the connected monitor object with the synchronized method. In the case of synchronized method, the lock object is:
- ‘.class’ object – if the given method is static.
- ‘this’ object – if the method is non-static. ‘this’ is the reference to the current object in which the synchronized method is invoked.
Java synchronized keyword is re-entrant in nature. It means if a synchronized method calls another synchronized method which requires the same lock, then current thread which is holding the lock can enter into that method without acquiring the lock.
Let us move ahead to the final topic of this article and point out the major differences between the synchronized keyword and synchronization block.
Difference between synchronized keyword and synchronized block
- When you use synchronized keyword with a method, it acquires a lock in the object for the entire method. This means that no other thread can use any synchronized method until the current thread that is invoked has finished its execution.
- Synchronized block acquires a lock in the object only between parentheses after the synchronized keyword is specified. This means that no other thread can acquire a lock on the already locked object until the block exits. But other threads will be able to access the rest of the code that is present in the method.
This brings us to the end of this article where we have discussed how exactly Synchronization in Java works. Hope you are clear with all that has been shared with you in this tutorial.
Check out the Java Certification Course by Edureka, a trusted online learning company with a network of more than 250,000 satisfied learners spread across the globe. We are here to help you with every step on your journey, for becoming a besides this java interview questions, we come up with a curriculum which is designed for students and professionals who want to be a Java Developer.
If you want to start a career in the Node JS Field then check out the Best Node JS Course by Edureka, a trusted online learning company with a network of more than 250,000 satisfied learners spread across the globe.
Got a question for us? Please mention it in the comments section of this “Synchronization in Java ”article and we will get back to you as soon as possible.