Concurrency

concurrency2SynchronizationDemo

Path
pkg7concurrency/concurrency2SynchronizationDemo.java
Package
pkg7concurrency
Study order
2
Run
Single-file source launch
Command
java pkg7concurrency/concurrency2SynchronizationDemo.java

There is no in-browser runner. This is the file from the curriculum, unchanged.

pkg7concurrency/concurrency2SynchronizationDemo.java
1package pkg7concurrency;2 3/*4 * concurrency2SynchronizationDemo.java5 * ------------------------6 * Demonstrates a RACE CONDITION and three fixes: synchronized, AtomicInteger,7 * and a lock. Also shows why `volatile` alone is NOT enough for count++.8 *9 * RACE CONDITION: count++ is read-modify-write (3 steps); concurrent threads10 * interleave and lose updates.11 */12import java.util.concurrent.atomic.AtomicInteger;13import java.util.concurrent.locks.*;14 15public class concurrency2SynchronizationDemo {16 17    static int unsafe = 0;                          // racy18    static int guarded = 0;                          // protected by `lock`19    static final AtomicInteger atomic = new AtomicInteger();20    static final Object monitor = new Object();21    static final ReentrantLock lock = new ReentrantLock();22    static int synced = 0;23 24    static void incUnsafe()  { unsafe++; }25    static void incSynced()  { synchronized (monitor) { synced++; } }26    static void incLocked()  { lock.lock(); try { guarded++; } finally { lock.unlock(); } }27 28    public static void main(String[] args) throws InterruptedException {29        final int THREADS = 8, PER = 50_000, EXPECTED = THREADS * PER;30 31        run("unsafe (race)", THREADS, PER, concurrency2SynchronizationDemo::incUnsafe);32        run("synchronized",  THREADS, PER, concurrency2SynchronizationDemo::incSynced);33        run("ReentrantLock", THREADS, PER, concurrency2SynchronizationDemo::incLocked);34        run("AtomicInteger", THREADS, PER, atomic::incrementAndGet);35 36        System.out.println("\nEXPECTED        = " + EXPECTED);37        System.out.println("unsafe          = " + unsafe + "   <- usually LESS (lost updates)");38        System.out.println("synchronized    = " + synced);39        System.out.println("ReentrantLock   = " + guarded);40        System.out.println("AtomicInteger   = " + atomic.get());41    }42 43    static void run(String label, int threads, int per, Runnable inc) throws InterruptedException {44        Thread[] ts = new Thread[threads];45        for (int i = 0; i < threads; i++) {46            ts[i] = new Thread(() -> { for (int j = 0; j < per; j++) inc.run(); });47            ts[i].start();48        }49        for (Thread t : ts) t.join();50    }51}