0

I was reading about volatile in java and here there is a nice explanation http://tutorials.jenkov.com/java-concurrency/volatile.html.

It says that volatile is good in situations...

where only Thread 1 writes to the shared counter variable, declaring the counter variable volatile is enough to make sure that Thread 2 always sees the latest written value.

volatile int counter = 0;

But when both Threads, Thread1 writes (counter++) to the volatile and Thread2 reads the volatile at the same time, Thread2 might get counter as 0. (Getting counter as 1 it would mean that Thread2 would wait for Thread1 to write but atomicity doesn't exist in volatile or Thread1 is slighty faster than Thread2. Ideally lets say they both the same)

So what is the point of volatile in this situation?

Michael
  • 41,989
  • 11
  • 82
  • 128
Nick
  • 2,818
  • 5
  • 42
  • 60
  • 1
    It's not clear what you're asking. Volatile is useful when you want to be able to see the latest value *at the point when you try to read*. It doesn't imply that the reader thread will process *every value* - that would be a producer-consumer relationship which would require a queue or a lock. – Michael Jun 11 '18 at 09:37
  • 1
    That is addressed on the same page: *"As soon as a thread needs to first read the value of a volatile variable, and based on that value generate a new value for the shared volatile variable, a volatile variable is no longer enough to guarantee correct visibility."* – jspcal Jun 11 '18 at 09:37
  • 1
    This is exactly why there is an [AtomicInteger#incrementAndGet()](https://docs.oracle.com/javase/10/docs/api/java/util/concurrent/atomic/AtomicInteger.html#incrementAndGet()). Volatile cannot be used in this case where read and write are done in a single action. – Jai Jun 11 '18 at 09:39

1 Answers1

1

Volatile is used to ensure that the modified counter value is propagated to all threads correctly. It also gives hints to the Java compiler not to optimize the variable in unsafe ways. So without volatile it is possible that:

int counter = 0;

Thread 1: modifies counter, setting it to 1. Java compiler optimizes code so value 1 is stored in CPU register or CPU cache.

Thread 2: several micro-seconds LATER, thread 2 reads counter and it is still 0 because thread 1 has not flushed counter into shared memory yet.

John Lim
  • 455
  • 4
  • 4
  • "several micro-seconds LATER" It doesn't have to be microseconds. AFAIK it's completely undefined by the JLS. It could theoretically take hours, weeks, months, years... – Michael Jun 11 '18 at 09:41
  • Michael, entirely correct. However please, years is a bit too much :) – John Lim Jun 11 '18 at 09:45
  • It was hyperbole, of course. That would be a terrible implementation. My point is that it's completely arbitrary so we should never make *any* assumptions about it, even assumptions as ridiculous as 'if we wait for a year, this will definitely be visible to all threads' – Michael Jun 11 '18 at 09:50