Master Java’s synchronized Keyword: When and How to Use It Effectively
This comprehensive guide explains Java's synchronized keyword, covering instance and static methods, synchronized blocks in various contexts, data visibility, instruction reordering, object selection, performance considerations, and alternatives, with clear code examples for multithreaded programming.
Java Concurrency Tools
The synchronized keyword marks methods or blocks as synchronized, ensuring that only one thread can execute the marked code at a time, which helps avoid race conditions.
Java synchronized Keyword
synchronized was Java's earliest mechanism for coordinating access to shared objects, but it is considered low‑level compared to the richer concurrency utilities introduced in Java 5.
Synchronized Instance Methods
Example of a synchronized instance method:
public class MyCounter {
private int count = 0;
public synchronized void add(int value) {
this.count += value;
}
}The method is synchronized on the instance that owns it, so only one thread can execute any synchronized instance method of that object at a time.
Synchronized Static Methods
Static methods can also be synchronized; they lock on the Class object:
public static MyStaticCounter {
private static int count = 0;
public static synchronized void add(int value) {
count += value;
}
}If multiple static synchronized methods belong to the same class, only one thread may execute any of them concurrently.
Synchronized Blocks in Instance Methods
Sometimes only a portion of a method needs synchronization. A synchronized block can be used for finer‑grained control:
public void add(int value) {
synchronized(this) {
this.count += value;
}
}The object supplied to the parentheses is the monitor; only one thread can hold the lock for that object at a time.
Synchronized Blocks in Static Methods
Static methods can contain synchronized blocks that lock on the Class object:
public static void log2(String msg1, String msg2) {
synchronized(MyClass.class) {
log.writeln(msg1);
log.writeln(msg2);
}
}Only one thread may execute any block synchronized on the same Class object at a time.
Synchronized Blocks in Lambda Expressions
Synchronization works inside lambda expressions and anonymous classes as well:
import java.util.function.Consumer;
public class SynchronizedExample {
public static void main(String[] args) {
Consumer<String> func = (String param) -> {
synchronized(SynchronizedExample.class) {
System.out.println(Thread.currentThread().getName() + " step 1: " + param);
try {
Thread.sleep((long) (Math.random() * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " step 2: " + param);
}
};
Thread thread1 = new Thread(() -> func.accept("Parameter"), "Thread 1");
Thread thread2 = new Thread(() -> func.accept("Parameter"), "Thread 2");
thread1.start();
thread2.start();
}
}Java Synchronization Example
Running two threads that share a single Counter instance demonstrates instance‑level synchronization:
public class Example {
public static void main(String[] args) {
Counter counter = new Counter();
Thread threadA = new CounterThread(counter);
Thread threadB = new CounterThread(counter);
threadA.start();
threadB.start();
}
}
class Counter {
long count = 0;
public synchronized void add(long value) {
this.count += value;
}
}
class CounterThread extends Thread {
protected Counter counter = null;
public CounterThread(Counter counter) {
this.counter = counter;
}
public void run() {
for (int i = 0; i < 10; i++) {
counter.add(i);
}
}
}If each thread uses a different Counter instance, the synchronized methods do not block each other.
Synchronized and Data Visibility
Without synchronized (or volatile), changes made by one thread may not become visible to others. Entering a synchronized block flushes visible variables; exiting commits changes to main memory.
Synchronized and Instruction Reordering
The JVM may reorder instructions for performance, but synchronized imposes ordering constraints similar to volatile, preventing reordering that could break correctness.
Choosing Synchronization Objects
Any object can be used as a monitor, but it is safest to synchronize on this or a freshly created new Object() to avoid accidental sharing of cached objects such as string literals or boxed primitives.
Limitations and Alternatives
synchronized allows only one thread at a time. For read‑heavy scenarios, consider ReadWriteLock. To allow N concurrent threads, use a Semaphore. Fairness and ordering must be implemented manually if required.
Performance Overhead
Entering and exiting synchronized blocks incurs some cost, though modern JVMs have reduced it. Avoid large synchronized sections and only protect the minimal code that truly requires mutual exclusion.
Synchronized Block Reentrance
A thread that already holds a lock can re‑enter another synchronized block guarded by the same monitor, enabling recursive calls without deadlock.
Synchronized Blocks in Cluster Setups
synchronized only coordinates threads within a single JVM. In a cluster of JVMs, additional mechanisms (e.g., distributed locks) are needed for cross‑process synchronization.
Cognitive Technology Team
Cognitive Technology Team regularly delivers the latest IT news, original content, programming tutorials and experience sharing, with daily perks awaiting you.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
