Reading — step 1 of 7
Learn
Java threads talk to each other through shared memory. The Java Memory Model (JMM) defines what reads see what writes — and the answer is more subtle than "the latest one."
The basic primitives:
Thread t = new Thread(() -> doWork());
t.start();
t.join(); // wait for it
Or the more idiomatic:
ExecutorService exec = Executors.newFixedThreadPool(4);
Future<Integer> f = exec.submit(() -> compute());
int result = f.get(); // blocks until done
exec.shutdown();
The visibility problem — without synchronization, one thread's writes may NEVER be seen by another:
class Worker {
boolean running = true;
public void stop() { running = false; }
public void run() {
while (running) {
// ... do work ...
}
}
}
stop() from one thread might not affect run() in another. The JIT can cache running in a register; without a memory barrier the cached value lives forever.
Fixes:
volatile— guarantees writes are visible to other threads:volatile boolean running = true;synchronized— both mutual exclusion AND visibility:synchronized (this) { running = false; }AtomicXxx—java.util.concurrent.atomic, lock-free volatile-like updates:AtomicBoolean running = new AtomicBoolean(true); AtomicInteger counter = new AtomicInteger(0); counter.incrementAndGet(); counter.compareAndSet(5, 10);
Happens-before — the JMM's contract:
- Writes within a thread happen-before later reads in the same thread
- An
unlockhappens-before a subsequentlockof the same monitor - A volatile write happens-before a subsequent volatile read of the same field
- A thread's
start()happens-before its first action - A thread's last action happens-before a successful
join()returning
Rules let you reason about visibility without studying CPU memory orders. When in doubt: synchronize, use volatile, or use Atomic*.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…