What does 'synchronized' mean?
Categories:
Understanding 'synchronized' in Java: A Deep Dive into Thread Safety

Explore the 'synchronized' keyword in Java, its role in multithreading, and how it prevents race conditions and ensures data consistency in concurrent applications.
In the world of concurrent programming, managing shared resources among multiple threads is a critical challenge. Without proper control, threads can interfere with each other, leading to data corruption, inconsistent states, and unpredictable program behavior. Java's synchronized
keyword is a fundamental mechanism designed to address these issues, providing a way to enforce thread safety and ensure data integrity.
What is 'synchronized'?
The synchronized
keyword in Java is a powerful tool for controlling access to shared resources by multiple threads. It ensures that only one thread can execute a synchronized block or method at any given time, effectively preventing race conditions and maintaining data consistency. When a thread enters a synchronized
block or method, it acquires a lock on the associated object or class. Other threads attempting to enter the same synchronized block or method will be blocked until the lock is released by the first thread.
sequenceDiagram participant ThreadA participant ThreadB participant SharedObject ThreadA->>SharedObject: Attempt to acquire lock activate SharedObject SharedObject-->>ThreadA: Lock acquired ThreadA->>SharedObject: Execute synchronized code ThreadA->>SharedObject: Release lock deactivate SharedObject ThreadB->>SharedObject: Attempt to acquire lock Note over ThreadB,SharedObject: ThreadB is blocked until lock is released activate SharedObject SharedObject-->>ThreadB: Lock acquired ThreadB->>SharedObject: Execute synchronized code ThreadB->>SharedObject: Release lock deactivate SharedObject
Sequence diagram illustrating how 'synchronized' manages thread access to a shared object.
How 'synchronized' Works: Locks and Monitors
At its core, synchronized
relies on the concept of intrinsic locks, also known as monitor locks. Every Java object has an intrinsic lock associated with it. When a thread invokes a synchronized
method or enters a synchronized
block, it attempts to acquire the lock for the object that owns the method or block. If the lock is available, the thread acquires it and proceeds. If the lock is already held by another thread, the current thread enters a waiting state until the lock is released. Once the thread exits the synchronized
block or method (either normally or due to an exception), the lock is automatically released.
synchronized
methods and synchronized
blocks is crucial. A synchronized
method locks the entire object, while a synchronized
block allows for more granular control by locking a specific object or class.Applying 'synchronized': Methods vs. Blocks
The synchronized
keyword can be applied in two main ways: to methods or to blocks of code. Each approach has its own use cases and implications for concurrency control.
public class Counter {
private int count = 0;
// Synchronized method: locks the 'Counter' object
public synchronized void increment() {
count++;
}
// Synchronized block: locks 'this' (the current Counter instance)
public void decrement() {
synchronized (this) {
count--;
}
}
// Synchronized static method: locks the 'Counter.class' object
public static synchronized void staticIncrement() {
// ... operates on static fields ...
}
// Synchronized block on a specific object
private final Object lock = new Object();
public void safeOperation() {
synchronized (lock) {
// ... thread-safe operations ...
}
}
public int getCount() {
return count;
}
}
When a non-static method is declared synchronized
, the lock is acquired on the instance of the object (this
). For static synchronized
methods, the lock is acquired on the Class
object itself (e.g., Counter.class
). A synchronized
block, on the other hand, allows you to specify any object as the lock. This is particularly useful when you need to protect only a portion of a method or when you want to use a different lock object than this
to avoid deadlocks or allow more concurrency for unrelated operations.