0

I am just starting to learn about java multi-threading and have been troubled with keyword volatile a lot.

Many tutorial talk about the visibility of volatile field, just like "volatile field becomes visible to all readers (other threads in particular) after a write operation completes on it". I have doubt about how could a completed write on field being invisible(ignore the situation that some compiler optimization may make the program did not read on the real field) to other Threads(or CPUS)?

As my understanding, a completed write means you have successfully written the filed back to cache, and according to the MESI, all others thread should have an Invalid cache line if this filed have been cached by them. One exception ( Since I am not very familiar with the hardcore, this is just a conjecture )is that maybe the result will be written back to the register instead of cache and I do not know whether there is some protocol to keep consistency in this situation or the volatile make it not to write to register in java.

In some situation that looks like "invisible" happens examples:

A=0,B=0; 
thread1{A=1; B=2;}  
thread2{if(B==2) {A may be 0 here}}

suppose the compiler did not reorder it, what makes we see in thread2 is due to the store buffer, and I do not think a write operation in store buffer means a completed write. Since the store buffer and invalidate queue strategy, which make the write on variable A looks like invisible but in fact the write operation has not finished while thread2 read A. Even we make field B volatile, while we set a write operation on field B to the store buffer with memory barriers, thread 2 can read the b value with 0 and finish. As for me, the volatile looks like is not about the visibility of the filed it declared, but more like an edge to make sure that all the writes happens before volatile field write in ThreadA is visible to all operations after volatile field read( volatile read happens after volatile field write in ThreadA has completed ) in another ThreadB.

By the way, since I am not an native speakers, I have seen may tutorials with my mother language(also some English tutorials) say that volatile will instruct JVM threads to read the value of volatile variable from main memory and do not cache it locally, and I do not think that is true. Am I right?

pythonHua
  • 61
  • 6
  • `I have doubt about how could a completed write on field being invisible to other Threads` The simple answer is that an optimizer will remove writes when it can. If the value in question has been hoisted into a register for efficiency then no write occurs. The volatile prevents that. – markspace Oct 16 '21 at 14:39
  • `volatile will instruct JVM threads to read the value of volatile variable from main memory and do not cache it locally` On some systems, a write to main memory is required. On others (notably Intel since about 2008) there's a QPI bus that makes the cache coherent and an actual write to main memory is not required. – markspace Oct 16 '21 at 14:44
  • (And as far as I know `volatile` in C and C++ requires non-temporal semantics and *does* require that the cache be bypassed and a main memory write executed.) – markspace Oct 16 '21 at 14:45
  • 2
    Re, "I am just starting to learn about java..." `volatile` is a simpler mechanism, under the hood, than `synchronized` or `ReentrantLock`, but using it in meaningful and correct ways is an _advanced topic._ Save it for later. IMO, you should build a solid understanding of the language before you dive into threads, and then build a solid understanding of correct and meaningful ways to use threads before you start experimenting with `volatile`. – Solomon Slow Oct 16 '21 at 14:51
  • "completed write means you have successfully written the filed back to cache" it _doesn't_ necessarily mean that for a nonvolatile variable. – Louis Wasserman Oct 16 '21 at 16:36
  • 1
    Like I already said in comments on [your previous question](https://stackoverflow.com/a/69571738/224132), cache is always coherent, or you wouldn't be running multiple Java threads across different cores. [Myths Programmers Believe about CPU Caches](https://software.rajivprab.com/2018/04/29/myths-programmers-believe-about-cpu-caches/) explains this; read it again. `volatile` means the JVM has to run a load or store instruction, making the value part of the cache-coherent view of memory that all cores share. Flushing cache lines to DRAM is always irrelevant for correctness / visibility. – Peter Cordes Oct 16 '21 at 18:44
  • 1
    Or in other words, "memory contents" is the *logical* view of memory state shared by CPU cores via coherent caches. That's what you're loading from / storing to. If any tutorials claim that `volatile` forces load/store that goes all the way to DRAM / main memory, they're wrong. People get mixed up between *compilers* "caching" values in registers, which are thread-private vs. CPUs caching memory in coherent caches which maintain the illusion of shared state. – Peter Cordes Oct 16 '21 at 18:48

0 Answers0