Assigning a reference to itself in Java has no effect, right? – WRONG!
You see this piece of code in your beloved code base….
referenceToSomethingImportant = referenceToSomethingImportant;
You immediately delete it since assigning a variable to itself will never do any thing. Of course the compiler or the JIT machinery is always going to optimize it away anyway. Right?
Oh yes, there might be another thread you exclaim. But then doing something that has no effect will still have no effect when multiple threads are doing it, eh? Then what?
You are neglecting to consider the fact that read-write-assignment can do something other then memory operations to store data. Visibilty. That’s the key.
If “value” were declared to be volatile, the JVM now cannot optimize away everything from that line that you decided to remove. Because besides the data, there is now a memfence / mfence / membar / barrier / whatever-for-your-architecture instruction that is also being inserted as part of that bit of code when it is translated to assembly language for your machine.
This is to make the happens before guarantees associated with volatile reads and writes work correctly. Specifically, a happens before at that pont was caused by the volatile read / write. That caused changes up to that point by the thread to be flushed out of what could have been buffered in the SRAM (static RAM) on a specific core in the CPU causing it to be visible to other the reads.
There are situations where piggybacking the flush of such changes caused by operations on volatile variables can help in squeezing out the last bits of performance in concurrent code by avoiding synchronization which has the overhead of locking besides providing the same visibility guarantees as volatile does.
Highly unrecommended for anyone but authors of concurrency libraries!
Tags: Concurrency, Java, JMM, JVM