Syntax
synchronized (lockObject) {\n // critical section\n}Examples
The Problem Without Synchronization
Multiple threads incrementing a shared counter can produce an incorrect result due to a race condition.
class Counter {
private int count = 0;
public void increment() { // NOT thread-safe
count++; // this is actually three steps: read, add, write
}
public int getCount() {
return count;
}
}
// Without synchronization, running this with multiple threads can produce
// a final count LESS than expected, because increments can be lost
// when two threads read the same value before either writes back.synchronized Method
Marking an entire method as synchronized, so only one thread can execute it at a time per object.
class Counter {
private int count = 0;
public synchronized void increment() { // now thread-safe
count++;
}
public synchronized int getCount() {
return count;
}
}
Counter counter = new Counter();
Runnable task = () -> {
for (int i = 0; i < 1000; i++) counter.increment();
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();synchronized Block
Synchronizing only the specific critical section, rather than an entire method, for finer-grained control.
class BankAccount {
private double balance = 100;
private final Object lock = new Object();
public void withdraw(double amount) {
synchronized (lock) { // only this block is protected
if (amount <= balance) {
balance -= amount;
}
}
// other, non-critical work can happen outside the lock
}
}Best practices
- Synchronize the smallest block of code necessary (a synchronized block) rather than an entire large method, to minimize how long threads wait on each other
- Always synchronize on a private, final lock object rather than "this" when possible, to prevent external code from accidentally locking on the same object
- Keep synchronized blocks free of slow operations (like network calls or file I/O) - holding a lock for a long time hurts overall concurrency
- Consider higher-level concurrency utilities from java.util.concurrent (like AtomicInteger or ConcurrentHashMap) instead of manual synchronized blocks when they fit your use case
Runtime & versions
Java Virtual Machine. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
Java Language Specification