The Java Memory Model (JMM) may be seen as an extension of the basic within-thread expression and statement evaluation rules described in the bulk of the Java Language Specification (JLS). For example, JLS expression rules state that a given thread evaluates any expression left to right. The JMM provides additional rules governing whether the "memory actions" in one or more threads of a program may be performed in parallel or out of order.
Memory actions are reads, writes, locks and unlocks, along with operations on java.util.concurrent.atomic objects. A write corresponds to the assignment of a field that modifies (only) that field, and a read obtains a value from some write that does not happen after this read. Reads and writes for all kinds of fields (array elements also behave as fields for these purposes) except non-volatile longs and doubles are atomic, so reads never return the values from partially completed writes. Lock and unlock actions are entries and exits of synchronized blocks or methods, or explicit lock() and unlock() operations on java.util.concurrent.locks objectss.
The JMM is defined in terms in terms of a happens-before relation that provides ordering rules for the effects of memory actions. Memory actions in different threads may in general be performed in any order. But if action A happens-before action B, then compilers, processors, and memory subsystems must preserve the ordering of their effects. For example, if A is a write and B is a read of the field written, and the pair fall under the happens-before relation, and there are no other writes, then the read in action B must return the value written in action A. If the pair does not fall under this relation, then the read might or might not return this value. Perhaps a better name for this relation is "must happen before". Actions that are not in this relation might or might not occur in some particular order; but those that do must occur in the given order.
The happens-before relation extends the JLS within-thread expression and statement evaluation rules, so these rules are at all times honored, consistently across all threads. Rigorously specifying what is meant by "consistently" in cases that entail apparent circularities and the like turns out to be challenging. See JLS chapter 17 for these and other details, many of which describe minimal properties of code that is not correctly synchronized, as well as other corner cases that are best avoided. More relevantly, the following rules derived from the specification may be of use when ensuring that code is correctly synchronized.
Initialization