When synchronization is not used in a multi-threaded application, multiple threads can access the same shared resource simultaneously, leading to race conditions and data inconsistencies. Without synchronization, the order in which threads access shared resources is unpredictable, and the final state of the shared resource may be incorrect.
Here’s an example of what can happen when synchronization is not used:
public class Counter {
private int count;
public void increment() {
count++;
}
public int getCount() {
return count;
}
}
The Main class:
public class Main {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
counter.increment();
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
counter.increment();
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("Count: " + counter.getCount());
}
}
In this example, we define a Counter class that has an increment() method to increment a counter variable, and a getCount() method to return the current value of the counter variable.
We then create two threads to increment the counter variable. Each thread runs a loop that calls the increment() method 10,000 times. We start the threads and wait for them to finish using the join() method.
Finally, we print the final value of the counter variable. If the increment() method were synchronized, we would expect the final count to be 20,000. However, since synchronization is not used, the final count is unpredictable and may be different each time the program is run.
Overall, when synchronization is not used in a multi-threaded application, race conditions and data inconsistencies can occur, leading to unpredictable and potentially incorrect results. By using synchronization, we can ensure that multiple threads access shared resources in a safe and predictable manner, and prevent race conditions and data inconsistencies.