package ch.claude_martin.foo; import java.util.concurrent.ExecutorService; import java.util.concurrent.ForkJoinPool; public class MyClass { static class Car { private String owner = "N/A"; public String getOwner() { return this.owner; } public void setOwner(String o) { this.owner = o; } } volatile Car car = null; public static void main(String args[]) throws InterruptedException { new MyClass().go(); } void go() throws InterruptedException { ExecutorService es = ForkJoinPool.commonPool(); Runnable taskA = () -> { car = null; }; Runnable taskB = () -> { car = new Car(); // we call yield() because it would be rather unlikely that the thread is // interrupted here. You can remove it, but it will take longer. Thread.yield(); car.setOwner("Jane"); }; Runnable taskC = () -> { final Car copy = car; // taskA might set this to null at any time if (copy != null) { final String owner = copy.getOwner(); if ("N/A".equals(owner)) { System.err.println(owner); System.exit(0);// Stop the VM because we got to read the initial value } // else System.out.println(owner); } }; while (true) { es.submit(taskA); es.submit(taskB); es.submit(taskC); } } }