Interview question
What are Race Conditions and Deadlocks? How do you prevent them? Race Conditions और Deadlocks क्या हैं? इन्हें prevent कैसे करते हैं?
Answer
Race conditions occur when multiple threads access shared data simultaneously, causing unpredictable results. Deadlocks occur when threads wait for resources held by each other. Prevention requires careful synchronization and lock ordering.
// Race Condition Example
public class RaceCondition {
private int counter = 0;
public void increment() {
counter++; // NOT atomic
}
public static void main(String[] args) {
RaceCondition rc = new RaceCondition();
// 10 threads, each increments 1000 times
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (int j = 0; j < 1000; j++) {
rc.increment();
}
}).start();
}
// Expected: 10000, Actual: ~5000 (race condition)
try {
Thread.sleep(1000);
System.out.println('Counter: ' + rc.counter);
} catch (InterruptedException e) {}
}
}
// Solution: Synchronization
public class FixedCounter {
private int counter = 0;
public synchronized void increment() {
counter++; // Thread-safe
}
}
// Deadlock Example
public class Deadlock {
private Object lock1 = new Object();
private Object lock2 = new Object();
public void method1() {
synchronized(lock1) {
System.out.println('Method1: lock1 acquired');
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized(lock2) { // Waits for lock2
System.out.println('Method1: lock2 acquired');
}
}
}
public void method2() {
synchronized(lock2) { // Acquired first
System.out.println('Method2: lock2 acquired');
try { Thread.sleep(100); } catch (InterruptedException e) {}
synchronized(lock1) { // Waits for lock1 (held by method1)
System.out.println('Method2: lock1 acquired');
}
}
}
public static void main(String[] args) {
Deadlock dl = new Deadlock();
new Thread(dl::method1).start();
new Thread(dl::method2).start();
// Both threads wait for each other - DEADLOCK!
}
}
// Deadlock Prevention:
// 1. Lock Ordering - always acquire in same order
public class FixedDeadlock {
private Object lock1 = new Object();
private Object lock2 = new Object();
public void method1() {
synchronized(lock1) { // Always lock1 first
synchronized(lock2) {
// Safe
}
}
}
public void method2() {
synchronized(lock1) { // Always lock1 first
synchronized(lock2) {
// Safe
}
}
}
}
// 2. Timeout - acquire locks with timeout
ReentrantLock lock = new ReentrantLock();
if (lock.tryLock(1, TimeUnit.SECONDS)) {
try {
// Do work
} finally {
lock.unlock();
}
}
// 4 conditions for deadlock (prevent any one):
// 1. Mutual Exclusion
// 2. Hold and Wait
// 3. No Preemption
// 4. Circular WaitRace Conditions:
Problem: Multiple threads same resource
Example: counter++ (3 operations)
Solution:
1. Synchronization
2. Atomic classes
3. Volatile (simple cases)
Deadlock:
Problem: Circular wait for locks
Thread A: has lock1, wants lock2
Thread B: has lock2, wants lock1
Prevention:
1. Lock Ordering - सभी threads same order में
2. Timeout - tryLock(timeout)
3. Avoid nested locks
4. Use high-level frameworks
4 Deadlock Conditions:
1. Mutual Exclusion
2. Hold and Wait
3. No Preemption
4. Circular Wait
(किसी एक को prevent करो)Was this answer clear?