Saltar a contenido

Week 13 - The Java Memory Model and java.util.concurrent Foundations

Conceptual Core

The JMM defines what a thread can see of another thread's writes, and when. Without it, every multi-threaded program is undefined behavior. The model is built on happens-before - synchronization actions create happens-before edges; without an edge, no visibility guarantee.

Mechanical Detail

  • Happens-before sources: program order within a thread; synchronized unlock → subsequent lock; volatile write → subsequent read; Thread.start → first action in the new thread; thread termination → join return; final-field freeze at constructor exit.
  • volatile: visibility + ordering, not atomicity. volatile long/double got atomic in modern specs; pre-JMM they could tear.
  • synchronized blocks vs ReentrantLock. The lock is now LockSupport.park-backed and cooperates with virtual threads (Loom).
  • java.util.concurrent: ConcurrentHashMap, CopyOnWriteArrayList, BlockingQueue family, Semaphore, CountDownLatch, CyclicBarrier, Phaser. Read the Javadoc; Doug Lea writes the best Javadoc in the language.
  • Atomics: AtomicInteger/AtomicLong/AtomicReference. Pre-9: Atomic*FieldUpdater. Post-9: VarHandle is preferred.
  • ThreadLocal - the perennial classloader-leak source in app servers. Avoid when possible; prefer scoped values (week 15).

Lab

Implement a single-producer single-consumer ring buffer two ways: with synchronized+wait/notify, and with VarHandle + acquire/release. JMH them. Run with -XX:+PrintAssembly (HotSpot debug build, or use the hsdis plugin on a normal build) and find the membar instructions.

Idiomatic Drill

Read JSR-133 (the JMM) cookbook. Re-read every volatile and synchronized use in a codebase you maintain.

Production Hardening Slice

Enable the race detector - wait, Java doesn't have one. The substitutes: ThreadSanitizer via the OpenJDK TSAN port (experimental), Lincheck (formal model-checker for concurrent classes), jcstress (Shipilëv's tool, for memory-model edge cases). Add a jcstress test for your ring buffer.

Comments