In multithreaded environments, multiple threads may access shared data simultaneously, leading to:
- race conditions,
- inconsistent results,
- unexpected behavior.
Synchronization ensures only one thread can access a critical section at a time.
Synchronized Keyword
public syncronized void increment() {
count++;
}
Locks the entire method - only one thread at a time can execute it per object.
Synchronized Block
public void increment() {
syncronized (this) {
count++;
}
}
Finer control - only part of the method is locked.
Static Synchronization
public static synchronized void log() {
// locks the class, not the instance
}
Used when you want to lock on the class object.
Common Problem: Race Condition
// Two threads modify 'count' at the same time → inconsistent result
count++; // not atomic!
Use synchronization to prevent this.
Java Lock API (java.util.concurrent.locks
)
Lock lock = new ReentrantLock();
lock.lock();
try {
// critical section
} finally {
lock.unlock();
}
Gives more control than synchronized (e.g. try-lock, fair locks).
Comparison
synchronized vs Lock
Feature | synchronized | Lock (ReentrantLock) |
---|---|---|
Simpler syntax | Yes | No (verbose) |
Explicit unlock | No | Yes (manual) |
Try-lock | Not supported | Supported |
Reentrancy | Yes | Yes |
Tip
Be ready to:
- explain what race conditions are and how to prevent them,
- write synchronized methods/blocks,
- compare synchronized vs ReentrantLock,
- mention the importance of unlocking in a finally block.
Parent: _Multithreading