The reason is that even though the reference is atomic, it is atomic in a very narrow sense.
If a thread writes a non volatile reference, what is guaranteed is that other threads will see the whole write or not see it at all (no word tearing/garbage).
But at no point it is guaranteed that any other thread will ever see it nor that they will be seen in the same order.
An AtomicReference
provides much stronger guarantees (besides the CAS operations), essentially they behave like volatile:
- Any writes that happened in thread A before a volatile write are visible in thread B after a subsequent volatile read of that variable
- volatile operations cannot be reordered