If a variable is not declared volatile
, then the rules in the previous sections are
relaxed slightly to allow store actions to occur earlier than would otherwise be
permitted. The purpose of this relaxation is to allow optimizing Java compilers to
perform certain kinds of code rearrangement that preserve the semantics of properly synchronized programs but might be caught in the act of performing memory
actions out of order by programs that are not properly synchronized.
Suppose that a store by T of V would follow a particular assign by T of V according to the rules of the previous sections, with no intervening load or assign by T of V. Then that store action would send to the main memory the value that the assign action put into the working memory of thread T. The special rule allows the store action to instead occur before the assign action, if the following restrictions are obeyed:
This last property inspires us to call such an early store action prescient: it has to know ahead of time, somehow, what value will be stored by the assign that it should have followed. In practice, optimized compiled code will compute such values early (which is permitted if, for example, the computation has no side effects and throws no exceptions), store them early (before entering a loop, for example), and keep them in working registers for later use within the loop.