When working with multithreading in Java, multiple threads often share the same resources. Without proper control, this can lead to incorrect results or unexpected behavior. This problem is known as a race condition.
To solve this, Java provides thread synchronization, which ensures that only one thread accesses a shared resource at a time.
In this guide, you’ll learn thread synchronization in Java with a simple example that clearly demonstrates how it works.
What is Thread Synchronization?
Thread synchronization is a technique used to control the access of multiple threads to shared resources.
It ensures that:
- Only one thread executes a critical section at a time
- Data consistency is maintained
- Race conditions are avoided
What is a Race Condition?
A race condition occurs when two or more threads try to access and modify shared data simultaneously, leading to unpredictable results.
For example, two threads updating a bank account balance at the same time may cause incorrect values.
Why Synchronization is Important
- Prevents data inconsistency
- Ensures thread safety
- Maintains correct program behavior
- Essential in real-world applications
Synchronization in Java
Java provides the synchronized keyword to achieve thread synchronization.
It can be used with:
- Methods
- Blocks
Example Without Synchronization (Problem)
Let’s first see what happens without synchronization.
class Counter {
int count = 0;
void increment() {
count++;
}
}
class Test {
public static void main(String[] args) throws Exception {
Counter c = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) c.increment();
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) c.increment();
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Count: " + c.count);
}
}
Expected Output: 2000
Actual Output: May be less than 2000
This happens due to race conditions.
Example With Synchronization (Solution)
Now let’s fix the problem using synchronization.
class Counter {
int count = 0;
synchronized void increment() {
count++;
}
}
class Test {
public static void main(String[] args) throws Exception {
Counter c = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) c.increment();
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) c.increment();
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Count: " + c.count);
}
}
Output
Count: 2000
How Synchronization Works
- The
synchronizedkeyword locks the method - Only one thread can execute it at a time
- Other threads must wait until the lock is released
Synchronized Block Example
You can also synchronize a specific part of code.
void increment() {
synchronized(this) {
count++;
}
}
Real-World Use Cases
- Banking applications
- Ticket booking systems
- Inventory management
- Multi-user applications
Common Mistakes
- Not synchronizing shared resources
- Overusing synchronization (performance issue)
- Ignoring thread safety
Best Practices
- Synchronize only necessary code
- Keep critical section small
- Avoid deadlocks
FAQ
What is thread synchronization?
It controls access of multiple threads to shared resources.
What is synchronized keyword?
It ensures only one thread executes a block at a time.
Why is synchronization needed?
To prevent race conditions and ensure data consistency.
Conclusion
Thread synchronization is essential in Java when working with shared resources. It prevents data inconsistency and ensures safe execution of multithreaded programs.
Understanding synchronization will help you build reliable and efficient applications.

Comments
Post a Comment