0

I am learning volatile with the famous book "On Java". The book said:" If a single thread writes to a variable and other threads only read it, you can get away with making that variable volatile" I do not understand why not need "volatile " to make sure write thread flush variable back to memory? if no volatile, if others thread will read dirty data because of local cache?

eric
  • 41
  • 5
  • 1
    *"others thread will read dirty data because of local cache?"* - yes – Zabuzard Mar 02 '22 at 15:52
  • Does this answer your question? [Java volatile keyword](https://stackoverflow.com/questions/33643800/java-volatile-keyword) – pringi Mar 02 '22 at 15:53
  • 2
    That's one possibility. Another is that the thread hasn't bothered to write the change to memory at all; i.e. it is keeping it a register. – Stephen C Mar 02 '22 at 15:54
  • Thanks! After reading the comments and answer. I get the answer it is necessary use volatile when 1 thread write and other threads reading the variable. I more confused about the book "On Java" said: " If a single thread writes to a variable and other threads only read it, you can get away with making that variable volatile" – eric Mar 03 '22 at 03:39
  • Of course, @eric, here "get away with" means to reliably obtain consistent behavior without engaging full synchronization. `volatile` is surprisingly difficult to use properly, as people tend to make incorrect assumptions about its semantics. Synchronization seems to be easier to reason about. – John Bollinger Mar 03 '22 at 16:06

2 Answers2

1

Modern CPUs have coherent caches. So if one CPU does a write (e.g. a plain write) to the cache, another CPU will see this write. This is the task of the cache coherence protocol. Writes do not need to be pushed to the main memory because that would be extremely slow. So please do not use this mental model because it is not how CPUs work.

In simple terms volatile has 3 purposes:

  1. atomicity: make sure that the read or write is atomic. This is mostly a concern for 32 bits machines and using 64-bit values like double/long.

  2. visibility: make sure that read/write isn't optimized out by the compiler.

  3. ordering: make sure that loads/stores don't get reordered with respect to other loads and stores. CPUs and compilers have huge liberty to reorder loads and stores as long as they can't be detected in a single thread. But another thread could observe the reordering of loads/stores in that thread.

pveentjer
  • 10,545
  • 3
  • 23
  • 40
0

The Java volatile keyword is used to mark a Java variable as "being stored in main memory". More precisely that means, that every read of a volatile variable will be read from the computer's main memory, and not from the CPU cache, and that every write to a volatile variable will be written to main memory, and not just to the CPU cache.

Actually, since Java 5 the volatile keyword guarantees more than just that volatile variables are written to and read from main memory. I will explain that in the following sections.

The Java volatile keyword guarantees visibility of changes to variables across threads. This may sound a bit abstract, so let me elaborate.

In a multithreaded application where the threads operate on non-volatile variables, each thread may copy variables from main memory into a CPU cache while working on them, for performance reasons. If your computer contains more than one CPU, each thread may run on a different CPU. That means, that each thread may copy the variables into the CPU cache of different CPUs.

See more in here

Lunatic
  • 1,519
  • 8
  • 24
  • I had run the "TaskRunner" example use JDK 8, it will get the right answer very quickly.It looks like JDK fix the issue now. – eric Mar 03 '22 at 03:50
  • Happy to hear ;) – Lunatic Mar 03 '22 at 06:48
  • 2
    Committing to main memory is a fallacy; this is not how modern CPUs work. Caches on modern CPUs are always coherent. For more detail see https://shipilev.net/blog/2016/close-encounters-of-jmm-kind/#myth-commit-semantics – pveentjer Mar 03 '22 at 10:54