Static Synchronization in Java
Static synchronization in Java means synchronizing on the class rather than on an object. A static synchronized method takes the lock of the Class object (such as Ticket.class), so only one thread at a time can run any static synchronized method of that class. It is used to protect static fields, which are shared by all objects of the class. Synchronizing on this can't protect them, because different objects have different locks. In this lesson, you will learn static synchronization and the mistake it fixes.
Syntax
public static synchronized int nextNumber() { ... }
// same lock, written as a block:
synchronized (Ticket.class) { ... }Example: Unique Ticket Numbers
Let's see an example where every new ticket must get a unique number from a static counter. The class has two ways to get a number: a wrong one that locks this, and a right one that locks the class.
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Ticket {
private static int next = 0;
private static int nextUnsafe = 0;
static synchronized int nextNumber() {
return ++next;
}
synchronized int nextNumberWrongLock() {
return ++nextUnsafe;
}
public static void main(String[] args) throws InterruptedException {
Set<Integer> good =
java.util.Collections.synchronizedSet(new HashSet<>());
List<Thread> threads = new ArrayList<>();
for (int t = 0; t < 4; t++) {
Thread th = new Thread(() -> {
Ticket mine = new Ticket();
for (int i = 0; i < 50_000; i++) {
good.add(nextNumber());
mine.nextNumberWrongLock();
}
});
threads.add(th);
th.start();
}
for (Thread th : threads) {
th.join();
}
System.out.println("Class lock: " + good.size() + " unique numbers");
System.out.println("Object lock reached 200000? "
+ (nextUnsafe == 200_000));
}
}Class lock: 200000 unique numbers
Object lock reached 200000? falseExplanation: nextNumber is static synchronized, so all four threads share one lock, Ticket.class, and all 200,000 numbers are unique. nextNumberWrongLock is an instance method: each thread locks its own Ticket object, so the threads don't exclude each other while they all change the same static field, and updates are lost. (On rare runs the wrong version might still reach 200,000 by luck, which is why the output is marked as a sample.)
Static and Instance Locks Are Separate
Common Mistakes
Protecting a static field with an instance lock. Every object has its own lock, so threads don't wait for each other.
Mixing static and instance synchronized methods on the same data. They use different locks.
Holding the class lock for slow work. It blocks every thread using any static synchronized method of the class.
Practice
- Easy: Write a class with a
static synchronizedmethod that returns the next order ID, and test it with three threads. - Harder: Rewrite
nextNumberas anAtomicIntegerand compare the code.
Key Takeaways
Was this tutorial helpful?