Does increment operators e.g count++; stores volatile data thread-locally?

Viewed 121

My goal is to understand how the volatile keyword works.

My expected result: The assertEquals did not fail.

My actual result: The assertEquals fail. (sometimes the actual count value are between 9991 to 9999).

I am assuming this happens because of the increment operators / count++ equals to

public void increment() {
  int temp = count;
  count = temp + 1;
}

and considering that, the temp attribute is stored thread-locally. Am I true?

Counter.java

public class Counter implements Runnable {
  private volatile int count = 0;
  public int getCount() { return count; }
  public void increment() { count++; }
  @Override
  public void run() { increment(); }
}

CounterTest.java

public class CounterTest {
  @Test
  void increment() {
    ExecutorService service = Executors.newFixedThreadPool(10);
    Counter counter = new Counter();
    for (int i = 0; i < 10000; i++) {
      service.execute(counter);
    }
    service.shutdown();
    service.awaitTermination(1, TimeUnit.SECONDS);
    assertEquals(10000, counter.getCount());
  }
}
1 Answers

My goal is to understand how the volatile keyword works

If that is your goal, then start looking at the JLS and the guarantees that volatile offers. volatile is not about atomic operations, i.e.: count++; is not atomic. As such, this :

assertEquals(10000, counter.getCount());

can fail, at any point in time.

volatile is about what some thread is supposed to "observe" when it has observed a written value to that variable, by another thread. There are many, literally many examples of what this means, probably the most famous one is this. Start there and build your knowledge up to the JLS.

Related