0

Oracle documentation states that:

Reads and writes are atomic for reference variables and for most primitive variables (all types except long and double).

Now I wonder why the volatile keyword is necessary in the following example to prevent an endless loop - the change of the int variable should be atomic and therefore instantly visible to everyone, shouldn't it?

public class HelloWorld
{
     // This doesn't work as expected
     private static int x = 0;
     //Following would work: private volatile static int x = 0;

     public static void main(String []args) throws Exception
     {
         Thread t1 = new Thread(() -> {
            try
            {
                Thread.sleep(1000);
                x = 1; //Should be atomic, right? 
            } catch (InterruptedException e) {}
        });

         System.out.println("Begin");
         t1.start();

         //The evaluation of the condition should also be atomic, right?
         while(x == 0)
         {
         }

         t1.join();
         System.out.println("End");
     }
}
Dave Newton
  • 158,873
  • 26
  • 254
  • 302
BudBrot
  • 1,341
  • 2
  • 24
  • 44
  • 1
    Atomicity isn't the issue--have you looked up what volatile means in Java? E.g., http://tutorials.jenkov.com/java-concurrency/volatile.html, though it's discussed all over the place. – Dave Newton Oct 07 '19 at 19:03
  • 2
    "Atomic" does not mean "instantly visible to everyone." When one thread performs an atomic operation on some data, that means that other threads will either see that it was completely done, or they will see that it was not done at all. No other thread will ever see the data in a state where the operation was only part-way done. – Solomon Slow Oct 07 '19 at 19:24

1 Answers1

2

Reads and writes are atomic, just not necessarily visible between threads.

volatile is needed to create a happens-before relationship: without it, there is no guaranteed ordering between a write in one thread and a read in another.

By marking a variable volatile, a write in one thread is guaranteed to be visible to all subsequent reads (until the next write, obv): the write is committed to main memory, and then reads read from main memory, rather than the value being held in cache.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243