What is Synchronization in Java?
Synchronization in Java
Synchronization in Java is that the
capability to regulate the access of multiple threads to any shared resource.
Java Synchronization could be a
higher possibility wherever we would like to permit only 1 thread to access the
shared resource.
Why use Synchronization?
The synchronization is especially
used to
- To prevent thread interference.
- To prevent consistency problems.
Types of Synchronization
There are two kinds of
synchronization:
- Process Synchronization
- Thread Synchronization
Here, we are going
to discuss solely thread synchronization.
Thread Synchronization
There are two types of thread
synchronization mutual exclusive and inter-thread communication.
- Mutual Exclusive
- Synchronized method.
- Synchronized block.
- Static synchronization.
- Cooperation (Inter-thread communication in
java)
Mutual Exclusive
Mutual Exclusive is one of a kind
that helps maintains threads from interfering with each other while sharing
data. It may be accomplished via the use of the following three ways:
- By Using Synchronized Method
- By Using Synchronized Block
- By Using Static Synchronization
Concept of Lock in Java
Synchronization is constructed around
an internal entity referred to as the lock or monitor. Each object contains a
lock-related to it. By convention, a thread that wants consistent access to an
object's fields must acquire the object's lock before accessing them, then unleash
the lock once it’s finished them.
From Java 5, the package java.util.concurrent.locks contains many lock
implementations
Understanding the problem without Synchronization
Unsynchronized Code
Let's take a simple BankAccount class below. It holds state within
the form of a balance, which might be increased and decreased using
the credit and debit methods. Once employed in a
single-threaded context, this object can behave as expected, crediting and
debiting the amounts specified.
public class BankAccount {
private double balance;
public void credit(double amount){
balance = balance + amount;
}
public void debit(double amount){
balance = balance - amount;
}
public double getBalance(){
return balance;
}
}
However, when multiple threads call the credit and debit methods at the same time, we will
find ourselves with unpredictable behavior and an incorrect balance. To visualize
this in action, the test method below uses an ExecutorService to submit a hundred account
debits and a hundred account credits, every for £100.
@Test
public void testBankAccountWithoutSynchronization1(){
BankAccount bankAccount = new BankAccount();
ExecutorService executorService = Executors.newFixedThreadPool(10);
IntStream.rangeClosed(1, 100).forEach(i->{
executorService.submit(()-> {
bankAccount.debit(100);
});
executorService.submit(()-> {
bankAccount.credit(100);
});
});
executorService.shutdown();
System.out.println("Final Balance: " +
bankAccount.getBalance());
}
After all debits and credits have run, we'd expect
the account to own a balance of zero. However, what I concluded with was a
balance of -100 as shown below. Note that if you are running the sample code,
it’s going to take a variety of runs before you see a non-zero result.
Final Balance: -100.0
So, What's the
Problem?
The credit method takes the present balance, adds a
nominative quantity to that, then assigns the new value back to balance. The problem is that adding a value
to balance and
then assigning that result back to balance isn’t an associate atomic operation. It means
that it does not happen as one distinct unit of work. Instead, a thread could
add the desired amount to the current balance, and
before it has a chance to assign the new value back to balance, the balance variable is also updated by
another thread. At this time, the balance value held by the primary thread is stale and
therefore the resulting variable assignment is wrong.
public void credit(double amount){
balance = balance + amount;
}
To resolve the problem, we want to confirm that balance
= balance + amount becomes an atomic operation, performed in isolation
by one thread at a time.
Java Synchronized Method
The simplest
way to accomplish this is by marking the method as synchronized
. A synchronized
the method uses an implicit lock to confirm that just one thread at a
time will enter the method. As a result, any shared state referenced inside the
method is not any longer vulnerable to being manipulated by multiple threads simultaneously.
During this instance, the shared state we're protecting is the account balance
.
public
synchronized void credit(double amount){
balance = balance + amount;
}
Hope you found this article useful enough to gain some clarity over the concept of Synchronization of Multithreading in Java. If you wish to suggest to me some new facts and ideas about the topic or would like to correct me somewhere, feel free to leave a comment below. I’d love to know what you think!
Thanks for reading!!!
Related Articles: | Inter-thread Communication In Java
Comments
Post a Comment