17.3 Rules about Variables
Let T be a thread and V be a variable. There are certain constraints on the actions
performed by T with respect to V:
- An use or assign by T of V is permitted only when dictated by execution by T of the Java program according to the standard Java execution model. For example, an occurrence of V as an operand of the
+
operator requires that a single use action occur on V; an occurrence of V as the left-hand operand of the assignment operator =
requires that a single assign action occur. All use and assign actions by a given thread must occur in the order specified by the program being executed by the thread. If the following rules forbid T to perform a required use as its next action, it may be necessary for T to perform a load first in order to make progress.
- A store action by T on V must intervene between an assign by T of V and a subsequent load by T of V. (Less formally: a thread is not permitted to lose its most recent assign.)
- An assign action by T on V must intervene between a load or store by T of V and a subsequent store by T of V. (Less formally: a thread is not permitted to write data from its working memory back to main memory for no reason.)
- After a thread is created, it must perform an assign or load action on a variable before performing a use or store action on that variable. (Less formally: a new thread starts with an empty working memory.)
- After a variable is created, every thread must perform an assign or load action on that variable before performing a use or store action on that variable. (Less formally: a new variable is created only in main memory and is not initially in any thread's working memory.)
Provided that all the constraints above and below are obeyed, a load or store action may be issued at any time by any thread on any variable, at the whim of the implementation.
There are also certain constraints on the read and write actions performed by main memory:
- For every load action performed by any thread T on its working copy of a variable V, there must be a corresponding preceding read action by the main memory on the master copy of V, and the load action must put into the working copy the data transmitted by the corresponding read action.
- For every store action performed by any thread T on its working copy of a variable V, there must be a corresponding following write action by the main memory on the master copy of V, and the write action must put into the master copy the data transmitted by the corresponding store action.
- Let action A be a load or store by thread T on variable V, and let action P be the corresponding read or write by the main memory on variable V. Similarly, let action B be some other load or store by thread T on that same variable V, and let action Q be the corresponding read or write by the main memory on variable V. If A precedes B, then P must precede Q. (Less formally: actions on the master copy of any given variable on behalf of a thread are performed by the main memory in exactly the order that the thread requested.)
Note that this last rule applies only to actions by a thread on the same variable.
However, there is a more stringent rule for volatile
variables (§17.7).