Race conditions and synchronized

Multithreading · lesson 3 of 38 · 4 min read

Watch an update get lost between two threads, then fix it with the simplest tool Java has.

Open this lesson in the learning hub

Key points

  • count++ is three steps: read, add, write. Two threads interleave, both read 7, both write 8, and one increment vanishes.
  • A race condition means the answer depends on timing. It passes on your laptop and fails under load.
  • synchronized gives mutual exclusion: only one thread at a time holds that object's monitor.
  • It fixes visibility too. Everything done before releasing a lock is visible to the next thread that acquires it.
  • Monitors are reentrant. A thread already holding the lock can enter another synchronized block on the same object.
  • Lock on a private final Object. Never lock on a String literal or a boxed number, since unrelated code shares those instances.

Example

public class Main {
    static final Object LOCK = new Object();
    static int unsafe = 0;
    static int safe = 0;

    public static void main(String[] args) throws InterruptedException {
        Thread[] threads = new Thread[4];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(() -> {
                for (int n = 0; n < 100_000; n++) {
                    unsafe++;                              // read, add, write: 3 steps
                    synchronized (LOCK) { safe++; }        // one indivisible step
                }
            });
            threads[i].start();
        }
        for (Thread t : threads) t.join();

        System.out.println("expected : 400000");
        System.out.println("unsafe   : " + unsafe + "  <- updates got lost");
        System.out.println("safe     : " + safe);
    }
}

If two threads touch the same mutable data, one of them has to wait.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Multithreading course, and every lesson in it is listed on the Multithreading contents page.