What is Race Condition in Java?
A race condition in Java occurs when multiple threads access and modify shared data simultaneously, and the final result depends on the unpredictable timing of thread execution.
In simple words:
Race condition happens when multiple threads compete to update the same resource without proper synchronization, causing inconsistent or incorrect results.
Why Race Condition Happens?
Race conditions occur because:
- Threads run concurrently
- Threads share common resources
- Operations are not atomic
- No synchronization is used
Race Condition Overview Diagram
Thread 1 Reads Value
|
v
Shared Variable = 100
^
|
Thread 2 Reads Same Value
|
v
Both Threads Modify Data Simultaneously
|
v
Incorrect Final Result
Real-World Analogy
Imagine:
- Two people editing the same bank account balance at the same time
- One deposit may overwrite another update
Bank Account Example
Initial Balance = 1000
|
+-------> Thread 1 Withdraws 200
|
+-------> Thread 2 Withdraws 300
|
v
Incorrect Final Balance Possible
Simple Race Condition Example
class Counter {
int count = 0;
public void increment() {
count++;
}
}
What Happens Internally?
count++ is NOT atomic.
Internally it performs:
1. Read current value 2. Increment value 3. Write updated value
Internal Execution Flow
Thread 1 Reads count = 5
Thread 2 Reads count = 5
|
v
Thread 1 Writes 6
Thread 2 Writes 6
|
v
Expected = 7
Actual = 6
Race Condition Demonstration
class Counter {
int count = 0;
public void increment() {
count++;
}
}
public class Main {
public static void main(
String[] args
) throws Exception {
Counter counter =
new Counter();
Thread t1 = new Thread(() -> {
for(int i = 0;
i < 1000;
i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for(int i = 0;
i < 1000;
i++) {
counter.increment();
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(
counter.count
);
}
}
Expected Output
2000
Actual Output May Be
1785 1932 1991
Why Output Changes?
Because thread execution order is unpredictable.
Race Condition Flow
Multiple Threads Access Shared Data
|
v
Threads Read Same Value Simultaneously
|
v
Threads Overwrite Each Other
|
v
Data Corruption Happens
How to Prevent Race Condition?
- synchronized keyword
- Locks
- Atomic classes
- Concurrent collections
- Immutable objects
Solution Using synchronized
class Counter {
int count = 0;
public synchronized void increment() {
count++;
}
}
How synchronized Solves Problem?
Only one thread can execute synchronized method at a time.
Synchronization Flow
Thread 1 Enters Critical Section
|
v
Thread 2 Waits
|
v
Thread 1 Finishes
|
v
Thread 2 Continues
What is Critical Section?
Critical section is the code block accessing shared resources.
Example
count++;
Using synchronized Block
public void increment() {
synchronized(this) {
count++;
}
}
Using ReentrantLock
import java.util.concurrent.locks.*;
class Counter {
private Lock lock =
new ReentrantLock();
int count = 0;
public void increment() {
lock.lock();
try {
count++;
}
finally {
lock.unlock();
}
}
}
Using AtomicInteger
Modern Java provides atomic classes for thread-safe operations.
AtomicInteger Example
import java.util.concurrent.atomic.*;
AtomicInteger count =
new AtomicInteger();
count.incrementAndGet();
Why AtomicInteger Better?
- Thread-safe
- Lock-free operations
- High performance
- Efficient concurrency
Race Condition vs Deadlock
| Feature | Race Condition | Deadlock |
|---|---|---|
| Problem | Incorrect Data | Threads Stuck Forever |
| Cause | Concurrent Modification | Circular Waiting |
| Effect | Data Corruption | Application Freeze |
Race Condition in Banking Systems
Banking systems are highly vulnerable to race conditions because:
- Multiple transactions update same account
- Balance consistency is critical
- Concurrent withdrawals may corrupt balances
Banking Race Condition Flow
ATM 1 Reads Balance = 1000
ATM 2 Reads Balance = 1000
|
v
Both Withdraw Simultaneously
|
v
Incorrect Balance Stored
Banking Solution
- Database transactions
- Locks
- Synchronization
- Atomic operations
Race Condition in E-Commerce Systems
E-commerce platforms face race conditions in:
- Inventory updates
- Order processing
- Coupon usage
- Payment processing
E-Commerce Example
Product Stock = 1
|
+-------> Customer A Buys Product
|
+-------> Customer B Buys Product
|
v
Overselling Happens
Race Condition in Spring Boot
Spring Boot applications may encounter race conditions in:
- Singleton beans
- Shared caches
- Concurrent API processing
- Async tasks
- Distributed services
Spring Boot Flow
Multiple REST Requests Arrive
|
v
Shared Service Object Modified
|
v
Race Condition Possible
Race Condition in Microservices
Distributed microservices face race conditions in:
- Distributed transactions
- Event processing
- Shared distributed caches
- Inventory synchronization
- Kafka consumers
Microservice Flow
Service A Updates Data
Service B Updates Same Data
|
v
Distributed Race Condition Occurs
How Distributed Systems Prevent Race Conditions?
- Distributed locks
- Optimistic locking
- Pessimistic locking
- Versioning
- Database transactions
Advantages of Preventing Race Conditions
- Data consistency
- Reliable systems
- Correct calculations
- Stable enterprise applications
- Safe concurrent processing
Disadvantages of Excessive Synchronization
- Reduced performance
- Thread contention
- Deadlock risk
- Lower scalability
Common Interview Mistake
Many developers think primitive operations are always atomic.
Actually:
- Operations like count++ are NOT atomic.
Another Common Mistake
Many developers think synchronized completely removes concurrency issues.
Actually:
- Improper synchronization can still create bugs or deadlocks.
Best Practices
- Use synchronization carefully
- Prefer atomic classes when possible
- Minimize shared mutable state
- Use immutable objects
- Use thread-safe collections
- Monitor concurrency issues in production
Realtime Enterprise Example
Online Ticket Booking Platform
Available Seats = 1
|
+-------> User A Books Seat
|
+-------> User B Books Same Seat
|
v
Double Booking Happens
|
v
Race Condition Occurred
Related Learning Topics
- What is Multithreading in Java
- What is use of Synchronized keyword in Java
- What is Deadlock in Java
- What is Block in Java
- What is Concurrency in Java
- What is Asynchronous communication in Spring Boot
- What are Distributed Transactions
Professional Interview Answer
A race condition in Java occurs when multiple threads concurrently access and modify shared mutable data without proper synchronization, causing unpredictable or incorrect results depending on thread execution timing. Race conditions commonly occur because operations such as incrementing variables are not atomic and involve multiple internal steps like read, modify, and write. Java provides several mechanisms to prevent race conditions including synchronized methods, synchronized blocks, ReentrantLock, AtomicInteger, thread-safe collections, immutable objects, and concurrent utilities. Enterprise applications, banking systems, Spring Boot applications, distributed microservices, Kafka consumers, e-commerce platforms, cloud-native architectures, and high-concurrency systems must carefully handle race conditions to ensure data consistency, transactional integrity, and reliable concurrent processing. Modern distributed systems additionally use optimistic locking, pessimistic locking, distributed transactions, and distributed locking mechanisms to prevent race conditions across multiple services and databases.
Frequently Asked Questions
What is race condition in Java?
Race condition occurs when multiple threads modify shared data concurrently without proper synchronization.
Why does race condition happen?
Because thread execution timing is unpredictable and shared data is accessed concurrently.
How can race conditions be prevented?
Using synchronized, locks, atomic classes, and thread-safe programming techniques.
Is count++ atomic in Java?
No, count++ is not atomic.
Where are race conditions common?
Banking systems, Spring Boot applications, distributed microservices, e-commerce platforms, and concurrent enterprise systems.