Synchronization
Java Synchronization: In-Depth Guide
1. What is Synchronization?
Definition
Mechanism to control multiple threads accessing shared resources
Prevents thread interference and memory consistency errors
Ensures thread safety and data consistency
Why Synchronization?
Race Conditions: When multiple threads access shared data
Data Inconsistency: Without sync, data can become corrupted
Memory Visibility: Changes made by one thread may not be visible to others
2. Types of Synchronization
A. Method Synchronization
class Counter {
private int count = 0;
synchronized void increment() {
count++;
}
}
B. Block Synchronization
class Counter {
private int count = 0;
void increment() {
synchronized(this) {
count++;
}
}
}
C. Static Synchronization
class Counter {
private static int count = 0;
synchronized static void increment() {
count++;
}
}
3. Key Synchronization Concepts
A. Monitor/Lock
Every object in Java has a monitor
Only one thread can own monitor at a time
synchronized keyword uses this intrinsic lock
B. Mutual Exclusion
class BankAccount {
private double balance;
synchronized void withdraw(double amount) {
if (balance >= amount) {
balance -= amount;
}
}
}
C. Memory Visibility
class SharedData {
private volatile boolean flag = false;
private int data = 0;
void updateData() {
data++;
flag = true; // Visible to other threads
}
}
4. Advanced Synchronization Techniques
A. ReentrantLock
class BankAccount {
private final Lock lock = new ReentrantLock();
private double balance;
void withdraw(double amount) {
lock.lock();
try {
if (balance >= amount) {
balance -= amount;
}
} finally {
lock.unlock();
}
}
}
B. ReadWriteLock
class CacheData {
private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
private Map<String, String> cache = new HashMap<>();
String read(String key) {
rwLock.readLock().lock();
try {
return cache.get(key);
} finally {
rwLock.readLock().unlock();
}
}
void write(String key, String value) {
rwLock.writeLock().lock();
try {
cache.put(key, value);
} finally {
rwLock.writeLock().unlock();
}
}
}
5. Common Interview Questions & Answers
Q1: What's the difference between synchronized method and synchronized block?
Answer:
Synchronized method locks entire method
Synchronized block locks specific section
Block synchronization is more efficient
Block allows finer control over lock duration
Q2: What is the 'volatile' keyword?
Answer:
Ensures variable is read from main memory
Prevents thread caching of variable
Provides visibility guarantee
Doesn't provide atomicity
Use cases: flags, status indicators
Q3: Explain object-level vs class-level locking
Answer:
Object-level: synchronized non-static methods/blocks
Class-level: synchronized static methods/blocks
Different locks, can run concurrently
Class lock is on Class object itself
Q4: What is thread starvation?
Answer:
Thread unable to gain regular access to shared resources
Causes: Priority issues, long-holding locks
Solution: Fair locks, proper timeout mechanisms
Q5: How to prevent deadlock?
Answer:
Lock ordering
Lock timeouts
Try-lock mechanism
Avoid nested locks
Use Lock interface instead of synchronized
6. Common Synchronization Problems
A. Deadlock
// Deadlock Example
class DeadlockRisk {
private Object lock1 = new Object();
private Object lock2 = new Object();
void method1() {
synchronized(lock1) {
synchronized(lock2) {
// code
}
}
}
void method2() {
synchronized(lock2) {
synchronized(lock1) {
// code
}
}
}
}
B. Producer-Consumer Problem
class Buffer {
private Queue<Integer> queue = new LinkedList<>();
private int size;
synchronized void produce(int item) throws InterruptedException {
while(queue.size() == size) {
wait();
}
queue.add(item);
notify();
}
synchronized int consume() throws InterruptedException {
while(queue.isEmpty()) {
wait();
}
int item = queue.remove();
notify();
return item;
}
}
7. Best Practices
Synchronization Guidelines
Keep synchronized blocks small
Don't synchronize immutable data
Avoid synchronizing on String literals
Use private final lock objects
Consider using concurrent collections
Prefer ReentrantLock for complex scenarios
Document thread safety
Performance Considerations
Minimize lock contention
Use lock stripping when possible
Consider using atomic classes
Balance synchronization granularity
8. Modern Alternatives
A. Atomic Classes
AtomicInteger counter = new AtomicInteger(0);
counter.incrementAndGet(); // Thread-safe increment
B. Concurrent Collections
ConcurrentHashMap
CopyOnWriteArrayList
BlockingQueue
ConcurrentLinkedQueue
C. CompletableFuture (Java 8+)
CompletableFuture<String> future = CompletableFuture
.supplyAsync(() -> "Result")
.thenApply(s -> s + " processed");
Last updated