Thread Synchronization
Thread synchronization in Java is the mechanism used to control access to shared resources in a multi-threaded environment. It ensures data consistency, thread safety, and predictable behavior when multiple threads execute concurrently. This is a very high-frequency interview topic.
Why Thread Synchronization Is Needed
In multithreading, multiple threads may access and modify shared data simultaneously, leading to:
- Race conditions
- Inconsistent results
- Data corruption
Example Problem (Race Condition)
class Counter {
int count = 0;
void increment() {
count++;
}
}
Multiple threads calling increment() → incorrect count
What Is Synchronization?
- Ensures only one thread accesses a critical section at a time
- Achieved using locks (monitors)
- Prevents race conditions
Synchronization in Java (Ways)
- Synchronized Method
- Synchronized Block
- Static Synchronization
- Inter-thread Communication (wait, notify) (preview)
1️⃣ Synchronized Method
Locks the object (instance).
class Counter {
int count = 0;
synchronized void increment() {
count++;
}
}
- ✔ Only one thread can execute this method per object
- ✔ Lock = this
2️⃣ Synchronized Block (Preferred)
Locks specific code, not entire method.
class Counter {
int count = 0;
void increment() {
synchronized (this) {
count++;
}
}
}
- ✔ Better performance
- ✔ Fine-grained control
3️⃣ Static Synchronization
Locks the class-level object.
class Counter {
static int count = 0;
static synchronized void increment() {
count++;
}
}
- ✔ Lock = Counter.class
- ✔ Shared across all objects
Object Lock vs Class Lock (Interview Favorite)
| Type | Lock Used |
|---|---|
| Instance method | Object lock (this) |
| Synchronized block | Specified object |
| Static method | Class lock (ClassName.class) |
What Is a Monitor Lock?
- Every Java object has an intrinsic lock (monitor)
synchronizedacquires this lock- Released when thread exits synchronized area
Synchronization Example (Correct Output)
class Counter {
int count = 0;
synchronized void increment() {
count++;
}
}
public 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(c.count); // 2000
}
}
Synchronization and Performance
- Synchronization adds overhead
- Excessive synchronization reduces performance
- Use minimal critical sections
Synchronization Does NOT Solve
- Deadlocks
- Thread starvation
- Livelocks
- (Handled separately)
Alternatives to synchronized (Preview)
- java.util.concurrent.locks.Lock
- ReentrantLock
- Atomic classes (AtomicInteger)
Common Beginner Mistakes
- Synchronizing entire methods unnecessarily
- Synchronizing on wrong object
- Forgetting static vs instance lock difference
- Assuming synchronization fixes all concurrency issues
Interview-Ready Answers
Short Answer
Thread synchronization ensures that only one thread accesses shared resources at a time.
Detailed Answer
In Java, thread synchronization is achieved using the synchronized keyword to control access to critical sections of code. It prevents race conditions and ensures data consistency by allowing only one thread to hold a lock on an object or class at a time.
Key Takeaway
Synchronization protects shared data, not threads. Use it carefully and minimally to balance correctness and performance.