title: Volatile doesn't work as expected
body: <p>So I'm reading Brian Goetz' JCIP and wrote a following code for experimenting with <code>volatile</code> behavior.</p>
  
  <pre><code>public class StatefulObject {
  
      private static final int NUMBER_OF_THREADS = 10;
  
      private volatile State state;
  
      public StatefulObject() {
          state = new State();
      }
  
      public State getState() {
          return state;
      }
  
      public void setState(State state) {
          this.state = state;
      }
  
      public static class State {
          private volatile AtomicInteger counter;
  
          public State() {
              counter = new AtomicInteger();
          }
  
          public AtomicInteger getCounter() {
              return counter;
          }
  
          public void setCounter(AtomicInteger counter) {
              this.counter = counter;
          }
      }
  
      public static void main(String[] args) throws InterruptedException {
          StatefulObject object = new StatefulObject();
  
          ExecutorService executorService = Executors.newFixedThreadPool(NUMBER_OF_THREADS);
  
          AtomicInteger oldCounter = new AtomicInteger();
          AtomicInteger newCounter = new AtomicInteger();
  
          object.getState().setCounter(oldCounter);
  
          ConcurrentMap&lt;Integer, Long&gt; lastSeen = new ConcurrentHashMap&lt;&gt;();
          ConcurrentMap&lt;Integer, Long&gt; firstSeen = new ConcurrentHashMap&lt;&gt;();
          lastSeen.put(oldCounter.hashCode(), 0L);
          firstSeen.put(newCounter.hashCode(), Long.MAX_VALUE);
  
          List&lt;Future&gt; futures = IntStream.range(0, NUMBER_OF_THREADS)
              .mapToObj(num -&gt; executorService.submit(() -&gt; {
                  for (int i = 0; i &lt; 1000; i++) {
                      object.getState().getCounter().incrementAndGet();
                      lastSeen.computeIfPresent(object.getState().getCounter().hashCode(), (key, oldValue) -&gt; Math.max(oldValue, System.nanoTime()));
                      firstSeen.computeIfPresent(object.getState().getCounter().hashCode(), (key, oldValue) -&gt; Math.min(oldValue, System.nanoTime()));
                  }
              })).collect(Collectors.toList());
  
          executorService.shutdown();
  
          object.getState().setCounter(newCounter);
  
          futures.forEach(future -&gt; {
              try {
                  future.get();
              } catch (InterruptedException e) {
                  e.printStackTrace();
              } catch (ExecutionException e) {
                  e.printStackTrace();
              }
          });
  
          System.out.printf("Counter: %s\n", object.getState().getCounter().get());
          long lastSeenOld = lastSeen.get(oldCounter.hashCode());
          long firstSeenNew = firstSeen.get(newCounter.hashCode());
          System.out.printf("Last seen old counter: %s\n", lastSeenOld);
          System.out.printf("First seen new counter: %s\n", firstSeenNew);
          System.out.printf("Old was seen after the new: %s\n", lastSeenOld &gt; firstSeenNew);
          System.out.printf("Old was seen %s nanoseconds after the new\n", lastSeenOld - firstSeenNew);
      }
  }
  </code></pre>
  
  <p>So I'm expecting that <code>newCounter</code> is always first seen only after <code>oldCounter</code> was last seen (I expect all threads to notice the update so none is referencing the stale counter). To observe this behavior I use two maps. But surprisingly, I constantly get output like this:</p>
  
  <pre><code>Counter: 9917
  Last seen old counter: 695372684800871
  First seen new counter: 695372684441226
  Old was seen after the update: true
  Old was seen 359645 nanoseconds after the new
  </code></pre>
  
  <p>Can you please explain where I'm wrong?</p>
  
  <p>Thanks in advance!</p>