A variable is any location within a Java program that may be stored into. This includes not only class variables and instance variables but also components of arrays. Variables are kept in a main memory that is shared by all threads. Because it is impossible for one thread to access parameters or local variables of another thread, it doesn't matter whether parameters and local variables are thought of as residing in the shared main memory or in the working memory of the thread that owns them.
Every thread has a working memory in which it keeps its own working copy of variables that it must use or assign. As the thread executes a Java program, it operates on these working copies. The main memory contains the master copy of every variable. There are rules about when a thread is permitted or required to transfer the contents of its working copy of a variable into the master copy or vice versa
The main memory also contains locks; there is one lock associated with each object. Threads may compete to acquire a lock.
For the purposes of this chapter, the verbs use, assign, load, store, lock, and unlock name actions that a thread can perform. The verbs read, write, lock, and unlock name actions that the main memory subsystem can perform. Each of these actions is atomic (indivisible).
A use or assign action is a tightly coupled interaction between a thread's execution engine and the thread's working memory. A lock or unlock action is a tightly coupled interaction between a thread's execution engine and the main memory. But the transfer of data between the main memory and a thread's working memory is loosely coupled. When data is copied from the main memory to a working memory, two actions must occur: a read action performed by the main memory followed some time later by a corresponding load action performed by the working memory. When data is copied from a working memory to the main memory, two actions must occur: a store action performed by the working memory followed some time later by a corresponding write action performed by the main memory. There may be some transit time between main memory and a working memory, and the transit time may be different for each transaction; thus actions initiated by a thread on different variables may viewed by another thread as occurring in a different order. For each variable, however, the actions in main memory on behalf of any one thread are performed in the same order as the corresponding actions by that thread. (This is explained in greater detail below.)
A single Java thread issues a stream of use, assign, lock, and unlock actions as dictated by the semantics of the Java program it is executing. The underlying Java implementation is then required additionally to perform appropriate load, store, read, and write actions so as to obey a certain set of constraints, explained below. If the Java implementation correctly follows these rules and the Java application programmer follows certain other rules of programming, then data can be reliably transferred between threads through shared variables. The rules are designed to be "tight" enough to make this possible but "loose" enough to allow hardware and software designers considerable freedom to improve speed and throughput through such mechanisms as registers, queues, and caches.
Here are the detailed definitions of each of the actions:
Thus the interaction of a thread with a variable over time consists of a sequence of use, assign, load, and store actions. Main memory performs a read action for every load and a write action for every store. A thread's interactions with a lock over time consists of a sequence of lock and unlock actions. All the globally visible behavior of a thread thus comprises all the thread's actions on variables and locks.