Types of Synchronization
- Process Synchronization
Manages resources across different processes to avoid conflicts, ensuring only one process accesses a shared resource at a time. - Thread Synchronization
Controls multiple threads within the same application, using methods like synchronized blocks, synchronized methods, and locks to ensure threads don’t concurrently modify shared resources. - Static Synchronization
Involves synchronizing static methods or blocks to ensure that only one thread can access a static resource of a class at any given time.
Concept of Synchronization
Synchronization in Java refers to the ability to govern different threads' access to a shared resource. When we only want one thread to access a shared resource, Java Synchronization is a better solution. The basic purpose of synchronization is to avoid thread interference and solve the random-access problem. This blog is mainly concerned with Thread Synchronization Techniques.
There are two types of thread synchronization in Java:
- Mutual Exclusion(When only one thread can access a shared space, resource, etc.)
- Cooperation(or Inter-thread communication)
Mutual Exclusive helps keep threads from interfering with one another while sharing data. It can be achieved by using the following three ways:
- By Using Synchronized Method
- By Using Synchronized Block
- By Using Static Synchronization
You can also read about the Multiple Inheritance in Java.
What is Locks in Java?
Synchronization is based on a lock or monitor, which is an internal entity. A lock is associated with every object. By convention, a thread that requires consistent access to an object's fields must first obtain the object's lock and then release it after it's finished. All other threads attempting to access the object’s field are blocked until the thread currently holding the object’s lock releases it.
The package java.util.concurrent.locks contain many lock implementations starting with Java 5.
Java Synchronized Method
If you declare any method as synchronized, it is known as a synchronized method. The synchronized method is used to lock an object for any shared resource. When a thread calls a synchronized method, the lock for that object is automatically acquired and released when the thread completes its task.
Understanding the Problem without Java Synchronization Method
Let us first try this multi-threaded program without synchronization and Try it on java online compiler.
Java
//Example of Java Synchronized Method
class ResourceClass {
int resource;
ResourceClass(int val) {
this.resource = val;
}
void UpdateandPrintResource(int n, int threadNum) {
System.out.println("Thread " + threadNum + " Starts....");
this.resource += n;
try {
Thread.sleep(400);
} catch (Exception e) {
System.out.println(e);
}
System.out.println("Value of Resource: "+this.resource);
System.out.println("Thread " + threadNum + " Ends....");
}
}
class T1 extends Thread {
ResourceClass t;
T1(ResourceClass t) {
this.t = t;
}
public void run() {
t.UpdateandPrintResource(5, 1);
}
}
class T2 extends Thread {
ResourceClass t;
T2(ResourceClass t) {
this.t = t;
}
public void run() {
t.UpdateandPrintResource(10, 2);
}
}
public class TestSynchronization {
public static void main(String args[]) {
ResourceClass resoruceInst = new ResourceClass(10);
T1 t1 = new T1(resoruceInst);
T2 t2 = new T2(resoruceInst);
t1.start();
t2.start();
}
}
You can also try this code with Online Java Compiler
Run Code
Output:
As you can see, there is no order in which the object is accessed and its function is called. This is the problem with no synchronization, there is no consistency in the order of accessing and updating any resource.
Understanding the Problem with Java Synchronization Method
Now let us see the same program with the synchronized method.
Java
//Example of Java Synchronized Method
class ResourceClass {
int resource;
ResourceClass(int val) {
this.resource = val;
}
synchronized void UpdateandPrintResource(int n, int threadNum) {
System.out.println("Thread " + threadNum + " Starts....");
this.resource += n;
try {
Thread.sleep(400);
} catch (Exception e) {
System.out.println(e);
}
System.out.println("Value of Resource: "+this.resource);
System.out.println("Thread " + threadNum + " Ends....");
}
}
class T1 extends Thread {
ResourceClass t;
T1(ResourceClass t) {
this.t = t;
}
public void run() {
t.UpdateandPrintResource(5, 1);
}
}
class T2 extends Thread {
ResourceClass t;
T2(ResourceClass t) {
this.t = t;
}
public void run() {
t.UpdateandPrintResource(10, 2);
}
}
public class TestSynchronization {
public static void main(String args[]) {
ResourceClass resoruceInst = new ResourceClass(10);
T1 t1 = new T1(resoruceInst);
T2 t2 = new T2(resoruceInst);
t1.start();
t2.start();
}
}
You can also try this code with Online Java Compiler
Run Code
Output:
Must Read Static Blocks In Java.
Example of Synchronized Method by Using an Anonymous Class
Java
class Counter {
private int count = 0;
// Synchronized method to increment the count
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
public class SynchronizedAnonymousClassExample {
public static void main(String[] args) {
Counter counter = new Counter();
// Creating multiple threads using an anonymous class
Thread thread1 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
}
});
Thread thread2 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
}
});
// Starting the threads
thread1.start();
thread2.start();
try {
// Wait for both threads to finish
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Output the final count
System.out.println("Final count: " + counter.getCount());
}
}
You can also try this code with Online Java Compiler
Run Code
Output
Final count: 2000
Frequently Asked Questions
What is Synchronization in Java?
Synchronization in java is the capability to control the access of multiple threads to any shared resource. In the Multithreading concept, multiple threads try to access the shared resources at a time to produce inconsistent results. Synchronization is necessary for reliable communication between threads.
Why do we need to use synchronization in multithreaded programming?
We need to synchronize the shared resources to ensure that at a time only one thread is able to access the shared resource. If an object is shared by multiple threads then there is a need for synchronization in order to avoid the Object's state getting corrupted.
What are the benefits of synchronization in Java?
Synchronization in Java ensures thread safety by preventing data corruption, avoiding race conditions, and maintaining data consistency across multiple threads. It enhances reliability in concurrent applications, allowing for coordinated access to shared resources and ensuring atomicity of operations.
When to use synchronized in Java?
Use synchronized when multiple threads access shared resources, such as variables or data structures, that require consistent states. It's essential in scenarios involving critical sections, where operations must be executed atomically to avoid data inconsistencies or unexpected behavior.
Conclusion
In this article, we have discussed Synchronization in Java. Synchronization is a crucial aspect of Java programming that enables developers to manage concurrent access to shared resources effectively. By implementing synchronization techniques, such as synchronized methods and blocks, Java applications can ensure thread safety and data integrity, preventing common issues like race conditions and data corruption.
Head over to our practice platform Code360 to practice top problems, attempt mock tests, read interview experiences, and much more.!