Stop a Thread Using a volatile Flag in Java
Problem
volatile guarantees that a write to a variable by one thread is immediately visible to every other thread that reads it.
Start a worker that loops until told to stop, then stop it cleanly from the main thread.
Java Program
public class VolatileStopFlag {
private static volatile boolean running = true; // writes are seen by every thread immediately
public static void main(String[] args) throws InterruptedException {
Thread worker = new Thread(() -> {
while (running) { // re-reads the volatile flag on every check
Thread.onSpinWait();
}
System.out.println("Worker saw the stop request and exited");
});
worker.start();
Thread.sleep(100); // let it spin for a moment
running = false; // ask it to stop
worker.join(2000);
System.out.println("Worker still alive: " + worker.isAlive());
}
}Output
Core Logic
The worker checks a shared flag on every loop iteration, and volatile makes sure it sees main's update.
- 1
runningis astatic volatile booleanthat starts astrue. - 2The worker loops while
runningis true. - 3Main sleeps briefly, then sets
running = false. - 4
join(2000)waits for the worker, andisAlive()confirms it stopped.
Key Point: Without volatile, the JIT compiler may hoist the flag read out of the loop, so the worker can spin forever without ever noticing the change.
Key Concepts
Approach 2: Using AtomicBoolean
import java.util.concurrent.atomic.AtomicBoolean;
public class VolatileStopAtomic {
public static void main(String[] args) throws InterruptedException {
AtomicBoolean running = new AtomicBoolean(true);
Thread worker = new Thread(() -> {
while (running.get()) {
Thread.onSpinWait(); // hint to the CPU that this is a busy-wait loop (Java 9+)
}
System.out.println("Worker stopped");
});
worker.start();
Thread.sleep(100);
boolean changed = running.compareAndSet(true, false); // only succeeds if it was still true
worker.join(2000);
System.out.println("Stop request applied: " + changed);
System.out.println("Worker still alive: " + worker.isAlive());
}
}
Output
Core Logic
AtomicBoolean gives the same visibility as volatile, plus atomic operations such as compare-and-set.
- 1The worker loops while
running.get()is true. - 2
compareAndSet(true, false)stops it and reports whether this call made the change. - 3
Thread.onSpinWait()tells the CPU the loop is a busy-wait.
compareAndSet returns true because the flag was still true when main changed it.Key Point: volatile gives visibility but not atomicity; use atomics when a check-then-update must happen as one step.
Key Concepts
Interview Questions
Why is Thread.stop() deprecated?
It kills a thread at any point, releasing its locks while data may be half-updated. Cooperative flags or interruption let the thread stop at a safe point.
Does volatile make count++ thread-safe?
No. volatile makes reads and writes visible, but count++ is a read, an add and a write that other threads can interleave.