Traditional Java memory model semantics guarantee covers a lot of the Java language. In this article, we will highlight a few of semantics, to better understand them. For the semantics described in this article, we will try to appreciate the motives of the existing Java memory model updates. Paper and JMM future updates related discussions, will be referred to JMM9.
1. Java Memory Model
Existing Java memory model, such as JSR133 (hereinafter referred to JMM-JSR133) as defined, designated as shared memory consistency model, and help provide for the development and JMM-JSR133 statements consistent definition. JMM-JSR133 specification's goal is to ensure that threads interact through memory semantics precisely defined, in order to allow the optimization and provide a clear programming model. JMM-JSR133 is designed to provide definitions and semantics, so that multithreaded programs is not only correct, but also is a high-performance, the impact is minimal and the existing code base.
With this in mind, we had about JMM-JSR133, a lack of over-specify or specify the semantics of guarantee, but the focus to community-wide discussion on how we can improve JMM9 on its topic.
2. JMM9 - sequential consistency - race data freedom
JMM-JSR133 talked about with respect to the operation of the program execution. Combined with the implementation of orderly operation, describing the relationship between those actions. In this article, we will extend some of this order and relationships, and then discuss what is consistent with the order of execution. Let's start with the "Program sequence" Start. Program sequence for each thread is a general order, a sequence of all operations performed by the thread. Sometimes, not all operations require sequential execution. Therefore, there is something only partially ordered relationship. For example, it happens-before and two are partially ordered relationship synchronized-with. When an operation occurs before another operation; the first operation of the second operation is not only visible, but also their order in before the second operation. Relations between the two operations is called happens-before relationship. Sometimes, you need to specify the order of some special operation, they are called "synchronization." volatile read and write, monitor locking and unlocking, etc. are examples of synchronous operation. A synchronous operation causes synchronized-with the relationship between the operation. synchronized-with the partial order relationship, which means that not all synchronous operation twenty-two are included within this relationship of. The overall sequence of all synchronization operations is called "synchronization sequence", each has a synchronous sequential execution.
Now let's talk about the same order of execution. When all read and write operations are generally orderly execution, it is considered to be consistent (SC) order. In SC execution, the read operation is always able to see the last value written to a particular variable. When SC execution performance is no "race data", the program is considered to be free of data race (DRF) of. When the program has two do not have access happens-before relations order, they visit the same variable and at least one is a write access occurs when a data race. Consistent (SC for DRF) sequential data race freedom mean behavior DRF program is sequentially consistent. But strictly support the same order at the expense of performance for the price, most systems will reorder memory operations to improve execution speed, and "hidden" delay expensive operation. At the same time, the compiler will reorder the code to optimize execution. In order to ensure the strict consistency of scenarios, these can not reorder memory operations or code optimization, so performance will be affected. JMM-JSR133 underlying compiler has been used, the interaction between the cache and the program invisible JIT, merged relaxed ordering and reordering any restrictions.
NOTE: expensive operations are those take up a lot of CPU cycles to complete, stop the execution pipeline.
For JMM9, the performance is an important consideration, and that any one programming language memory model, in theory, should allow developers to take advantage of the weakly ordered memory model architecture (weakly-ordered) advantage. Successful implementations and examples are relaxing strict order, especially in a weak orderly architecture.
NOTE: Weak sequence is one that can reorder reads and writes, and require explicit memory barrier curb this reordering architecture.
3. JMM9 - issue out of nothing
JMM-JSR133 Another major semantic is "nothing" (Out-of Thin Air, OoTA) value is prohibited. It happens-before models sometimes creates variable values and "nothing" to read, because it does not contain the causal conditions. It is important, relations caused by its own will not use the concept of data dependence and control, in the example below we will see the correct synchronization code, by the writing itself is illegal to write due.
(Note: x and y are initialized to 0) -
r1 = x;
r2 = y;
if (r1! = 0)
if (r2! = 0)
y = 42;
x = 42;
This happens-before code is the same, but not really consistent with the order. For example, if x = r1 is written to see 42, and the write Y = r2 saw 42, the value of x and y is 42, which is the result of a race condition data.
r1 = x;
y = 42;
r2 = y;
x = 42;
Here, the variables are written to the variable before reading, reading will see the relevant written, which will lead to OoTA results.
Note: Data may produce results suggest race, which will eventually transform itself into a self-fulfilling prophecy. OoTA ensure that the rules of adhering to causality. The current thinking is that you can avoid speculative causal relationship. JMM9 aimed at finding reasons OoTA and improved way to avoid OoTA.
To disable OoTA value, some of them written to wait to read the data to avoid race conditions. Therefore, JMM-JSR133 defined OoTA ban formally rejected OoTA read. The formal definition includes memory model "execution and causal conditions." Basically, when all of the submitted program operation, a good execution to satisfy the causality condition.
Note: You can see each read write to the same variable, the execution of a good follow within a thread, happens-before and synchronization-order consistent implementation.
As you may already know, JMM-JSR133 defined strictly defined, let OoTA value invasion. JMM9 designed to detect and correct formal definition to allow some common optimization.
Volatile Operation 4. JMM9 Non-Volatile variable on
First, the keyword 'Volatile' What does it mean? Java's volatile to ensure the interaction between threads, so that when a thread writes a volatile variable, not only the written visible to other threads, and other threads can see that thread all writes to volatile variables.
Then the non-volatile variable and what happened? Non-volatile variables are not volatile keyword to ensure the benefits of interaction. Therefore, the compiler can use the cached value of non-volatile variable instead of volatile guarantee, volatile variable will always be read from memory. happens-before the model can be used to bind to synchronize access to the non-volatile variable.
Note: any field declared as volatile does not mean that there is a lock to participate. So volatile than the use of locks to synchronize cheaper. However, important to note that when there are multiple methods volatile field, may be more expensive than using locks.
5. JMM9 - write atomicity problems and word division problems
JMM-JSR133 were for shared-memory parallel algorithm provides read and write atomicity guaranteed (with exception). Exception is non-volatile long integer and double-precision floating-point writing are treated as two separate and written definition. Thus, a 64-bit value can be written to two 32-bit, respectively, when a thread is executing a read, if a written therein has not been completed, the thread may see only half the correct value, and thus lose atomicity . This is an example of atomic guarantees depends on the underlying hardware and memory subsystems. For example, the underlying assembler instruction should be able to handle the size of the operand to ensure atomicity, or if the read or write operation must be divided into more than one operation, will eventually destroy the atomic (as in the example of non-volatile long integer and double precision floating-point values). Similarly, if more than a generation to achieve because of the memory subsystem transactions, it will destroy atomic.
NOTE: volatile long integer and double-precision floating-point fields and references are always guaranteed atomic read and write
Bit-based design is not an ideal solution, because if the 64-bit exception is deleted, then the 32-bit architecture will suffer. If does not work on 64-bit architecture, if desired atomic, then we had to introduce "volatile" as long integer and double-precision floating-point, even if the underlying hardware can guarantee atomic operations. For example: volatile type field does not need to be defined as double precision floating point, because the underlying architecture, or ISA, floating-point unit can handle 64-bit wide demand atomic field. JMM9 purpose is to determine the hardware provides atomicity guarantees.
JMM-JSR133 written ten years ago; since then the number of bits processor has evolved, it has become the 64-bit processing mainstream digits. Immediately it is emphasized that, JMM-JSR133 proposed compromise for 64-bit read and write, although 64-bit value can be generated by any atomic structure, some of the infrastructure is still necessary to request a lock. Now, this makes these architectures 64-bit read and write operations are very expensive. On 32-bit x86 architecture, if you can not find a reasonable 64-bit atomic operations to achieve, the atomicity will not change.
Note: In language design, a potential problem, the keyword "volatile" has been given too much meaning. Running hard to make out, in order to restore users volatile atomic (so it can be stripped out in the 64-bit platform), or for the purpose of memory sort.
When talking about access atomicity, read and write operations of independence is an important consideration. Write a specific field should not be read or written with other fields have interaction. JMM-JSR133 guarantee means that synchronization should not be required to provide sequential consistency. Therefore, JMM-JSR133 ensure prohibition is called "word splitting" problem. Basically, when updating an operand hope on all operands generate lower than the base architecture of granular operations, we will encounter the "tear the word" problem. An important point to remember is that one of the reasons the word tear problem is that 64-bit long integer and double-precision floating-atoms are not given guarantees. Word torn JMM-JSR133 is prohibited in JMM9 continue to keep it that way.
6. JMM9 - final field problems
Compared with other fields, final field is different. For example, a thread with a final field x read a "fully initialized" of the object; object "is fully initialized", the card can read the initial value of the final field y, but not guaranteed "normal" non-final field nonX.
Note: The "full initialization" refers to the object's constructor completed.
Given the above, there are some simple things that can be fixed in the JMM9. For example: volatile type field, volatile field is initialized in the constructor does not guarantee the visibility, even for instance itself is visible. Therefore, the question is, whether the final field should be expanded to ensure that all the fields, including the initialization volatile field? In addition, if a fully initialized object "normal" non-final field value does not change, if we can guarantee to the final field of the "normal" field.