3

Can the optimizations performed by the Java compiler (version 5 or later) remove the "volatile" declaration of a variable?

More precisely, can a volatile variable be turned into a non-volatile variable in any of the following cases:

  • if there is no multithreading, i.e. if an application never uses more than one thread?

  • if a volatile variable is written by one thread but never accessed by any other thread?

  • if a volatile variable is read by several threads but never modified (read only, no writes)?

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
wiseowl4
  • 33
  • 2

1 Answers1

3

The volatile keyword requires that certain guarantees are satisfied when reading and writing the variable. It doesn't really make sense to talk about "removing the declaration"—no, that can't happen, because the only way that makes sense would be if the compiler ignored the declaration in your source code.

But if you are running the code in a context (e.g., single-threaded) where you couldn't tell that the runtime is actively working to meet those requirements, it is permissible for the runtime to skip that extra work.

Of your examples, the only case that might be determined at compile-time is a variable that is only written, and never read. In that case, the compiler could skip writes (if a variable is written, and no one is around to read it, does it make a sound?), but the the Java Memory Model still makes some guarantees about happens-before relationships around writing a volatile variable, and those still have to be upheld, so it wouldn't make sense to optimize that away at compile-time.

erickson
  • 265,237
  • 58
  • 395
  • 493
  • Thank you very much for your answer, it's now clearer for me. However, even if ignoring the volatile declaration doesn't make sense at compile-time, if I understand correctly, it's possible at runtime? – wiseowl4 Jan 07 '20 at 19:37
  • Also, if we are in the situation you described, i.e. a volatile variable only written, never read. Even at runtime, if the optimizations are allowed to skip the writes, they would still have to maintain the happens-before relationships around the writes (i.e., no reordering of the previous statements after the writes, flushing everything to the main memory when the writes should occur)? – wiseowl4 Jan 07 '20 at 19:49
  • @wiseowl4 I am not aware of anything in the JLS or JVM specifications that would prohibit a JVM from optimizing away things like flushing registers to main memory, if the difference was not observable to the program. While I'm not aware of any runtimes that do that today, I think it would make a lot of sense on some limited hardware platforms, like an embedded processor. Regarding your second comment, yes, the volatile access would still act as a synchronization point, so all other happens-before relations should hold. – erickson Jan 07 '20 at 19:58