Yes, there are multiple ways to solve a race condition depending on what you’re doing and how critical performance is.
Let’s go over the most common and effective ways 🔧:
🛠️ 1. Use synchronized
This is the most straightforward way to make a block or method thread-safe.
Example:
class Counter {
private int count = 0;
public synchronized void increment() {
count++; // now thread-safe
}
public synchronized int getCount() {
return count;
}
}
synchronized
ensures only one thread can access that code at a time.
It also establishes visibility (thread sees the latest value).
⚙️ 2. Use AtomicInteger
(Lock-free, efficient)
If you’re dealing with simple operations on a single variable, use Java’s atomic classes.
import java.util.concurrent.atomic.AtomicInteger;
class Counter {
private final AtomicInteger count = new AtomicInteger(0);
public void increment() {
count.incrementAndGet(); // atomic & thread-safe
}
public int getCount() {
return count.get();
}
}
Behind the scenes: uses CAS (Compare-And-Swap).
Great for counters, flags, or sequences.
🧱 3. Use ReentrantLock
for Fine-Grained Control
If you need flexible locking, like:
- Try-lock with timeout
- Fair locking
- Unlocking in different places
import java.util.concurrent.locks.ReentrantLock;
class Counter {
private int count = 0;
private final ReentrantLock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock(); // always release!
}
}
public int getCount() {
return count;
}
}
🧪 4. Use volatile
(Visibility only – not for compound actions!)
If your issue is visibility, not atomicity (e.g. flags), you can use volatile
.
volatile boolean running = true;
⚠️ But volatile
is not safe for things like x++
!
💡 Bonus: Higher-Level Solutions
Tool | Use Case |
---|---|
ConcurrentHashMap | Thread-safe key-value storage |
CopyOnWriteArrayList | Thread-safe list with few writes |
ExecutorService | Avoid managing threads manually |
Semaphore , CountDownLatch , CyclicBarrier | Coordinate threads |
🧠 Summary Table
Method | Atomic? | Visible to Threads? | Best For |
---|---|---|---|
synchronized | ✅ Yes | ✅ Yes | Critical sections, simple sync |
AtomicInteger | ✅ Yes | ✅ Yes | Counters, simple operations |
ReentrantLock | ✅ Yes | ✅ Yes | Advanced locking scenarios |
volatile | ❌ No | ✅ Yes | Flags, stop signals |