Java memory model

Source: Internet
Author: User
Tags visibility volatile

First, what is the Java memory model

The Java Virtual Machine specification attempts to define a Java memory model (MODEL,JMM) that masks the access differences of various hardware and operating systems to allow Java programs to achieve consistent memory access across various platforms. prior to this, mainstream programming languages (such as C + +, etc.) directly use the physical hardware and operating system's memory model, therefore, due to differences in memory models on different platforms, it is possible to cause the program to be completely normal on a set of platforms, while concurrent access on another set of platforms is often error- Therefore, it is not allowed to write programs for different platforms under certain scenarios.

The Java memory model needs to be sufficiently rigorous to make Java's concurrent memory access operations ambiguous, and the Java memory model must be loosely defined enough to allow the virtual machine's implementation to have enough free space to take advantage of the various features of the hardware to get better execution speed. After a long period of validation and patching, JDK1.5 (implemented JSR-133) was released, the Java memory model has matured and perfected, together to look at.

Second, main memory and working memory

The main purpose of the Java memory model is to define the access rules for each variable in the program, that is, the underlying details of storing variables in the virtual machine into memory and removing variables from memory. Note that the variables here do not include local variables and method parameters, because they are thread-private, are not shared, and naturally there is no competition, and the variables here should be instance fields, static fields, and elements that make up the array object.

The Java memory model specifies that all variables are stored in main memory (such as part of the virtual machine's physical memory) and that each thread has its own working memory (such as the cache in the CPU ). the working memory of the thread holds a copy of the variable to main memory used by the thread, and all operations of the thread on the variable (read, assign) must be made in working memory, not directly read and write to the variables in main memory . Variables in the other's working memory cannot be accessed directly between different threads, and the transfer of variable values between threads needs to be done through main memory, with the threads, main memory, and working memory interacting as shown:

Three, inter-memory interaction operations

The following 8 operations are defined in the Java memory model for implementation details of the specific interaction protocol between main memory and working memory, i.e. how a variable is copied from main memory to working memory, how to synchronize from the working memory back to main memory, and the virtual machine implementation must ensure that each of the operations mentioned below is atomic, Not to be divided:

1. Lock (Lock): A variable acting on the main memory, which identifies a variable as a thread-exclusive state.

2. Unlock (unlock): A variable that acts on the main memory, releasing a variable that is in a locked state, and the released variable can be locked by another thread.

3. READ: A variable acting on the main memory that transfers the value of a variable from main memory to the working memory of the thread for subsequent load actions to use.

4. Load (load): A variable that acts on the working memory, which puts the value of the variable that the read operation obtains from main memory into a variable copy of the working memory.

5. Use: A variable acting on the working memory that passes the value of a variable in the working memory to the execution engine, which will be performed without a virtual opportunity to a byte-code instruction that needs to use the value of the variable.

6. Assign (Assignment): A variable in working memory that assigns a value received from the execution engine to a variable in the working memory, and performs this operation whenever the virtual opportunity is assigned to a byte-code instruction that assigns a value to a variable.

7. Store: A variable in working memory that transfers the value of a variable in the working memory to the main memory for subsequent write operations.

8. Write (write): A variable that acts on the main memory, which puts the store operation from the value of the variable in the working memory into the variable of the main memory.

If you want to copy a variable from main memory to working memory, you need to do the following two things in a smooth way :

(1) Read operation performed by the JVM main memory;

(2) The corresponding load operation is performed by the Java thread's working memory.

Conversely, if you synchronize a variable from the working memory back into main memory, there are two actions:

(1) storage (store) operations performed by the Java thread's working memory;

(2) The corresponding write operation performed by the JVM's main memory.

The Java memory model only requires that the above operations must be executed sequentially, without guarantee that continuous execution is required. That is, between read and load, the store and write can be inserted between the other instructions, such as the main memory of the variable A, b access, the possible order is read A,read B,load b, load a.

The Java memory model also stipulates that when performing the eight basic operations above, the following rules must be met:

1. One of the read and load, store, and write operations is not allowed to appear separately.

2. A thread is not allowed to discard its most recent assign operation, that is, the variable must be synchronized back to main memory after it has changed in working memory.

3. One thread is not allowed to synchronize data from the working memory of the thread back to main memory for no reason.

4, a new variable can only be born from the main memory, not allowed in working memory directly using a non-initialized (load or assign) variable.

5 . A variable is allowed only one thread to lock it at the same time, but the lock operation can be repeated multiple times by the same thread, and once the lock is executed multiple times, the variable will be unlocked only if the same number of unlock operations are performed.

6 . If you perform a lock operation on the same variable, it will empty the value of this variable in the working memory, and the load or assign operation initializes the value of the variable before the execution engine uses the variable.

7, if a variable is not locked by the lock operation beforehand, it is not allowed to unlock operation, and does not allow to unlock a variable that is locked by another thread.

8 . Before performing a unlock operation on a variable, you must first synchronize this variable back into main memory.

Iv. special rules for volatile variable types

As stated above,the operation of READ,LOAD,STORE,WR ite is atomic , that is, the execution period will not be interrupted! But there may be interruptions between atomic operations ! for normal variables, if the copy of the main memory variable value in a thread is updated, it cannot be immediately reflected in other variables because each Java thread has a private working memory that stores the variable copies of the main memory that the thread needs to use! (such as instance field information, type of static variable, array, object ...) )

A A, a, two threads directly read or write the working memory of the thread! The process of using data from A and b to be transferred from their working memory to the same piece of main memory is time-lag, or there is isolation! In layman's words they can't see! That is, the variables in a thread that were previously said to have been modified are not immediately visible to other threads! If you need to be visible immediately in other threads , you need to use the volatile keyword. Now elicit the volatile keyword:

keyword volatile can be said to be the most lightweight synchronization mechanism provided by a Java virtual machine. Once a variable is defined as volatile, it will have two features:

1, to ensure that this variable "visibility" of all threads, so-called "visibility" refers to when a thread modifies the value of this variable, the new value for other threads can be immediately known, and ordinary variables do not do this, The value of the normal variable is passed through the thread between threads and must be done through main memory. For example, thread a modifies the value of an ordinary variable, then writes the value of the variable back to main memory, and another thread B reads the thread A after the write-back has finished, and the value of the new variable is visible to threads B. In addition, the operation in Java is not atomic, which causes the operation of volatile variables to be as unsafe as concurrency. Again,volatile only guarantees visibility and does not guarantee that operations based on volatile variables are safe in concurrency.

2 . The second semantics of using volatile variables is to prohibit command reordering optimizations , and ordinary variables will only ensure that the correct results are obtained in all areas that depend on the result of the assignment during the execution of the method. There is no guarantee that the order of variable assignment operations is consistent with the order of execution in the program code.

Summarize the special rules defined by the Java memory model for volatile variables:

1. In working memory, each time a variable is used, the line must refresh the most recent value from the main memory to ensure that the value of the changes that other threads have made to the variable is visible.

2. In working memory, each time a variable is modified, it must be immediately synchronized back to main memory to ensure that other threads can see the changes they have made to the variable.

3. Volatile modified variables are not optimized by instruction reordering, ensuring that the code executes in the same order as the program.

V. Atomicity, Visibility, order

The Java memory model is built around the three characteristics of how atomicity, visibility, and ordering are handled in the concurrency process, to look at it one at a glance:

1. atomicity (atomicity)

The Java memory model directly guarantees the operation of atomic variables including read, load, assign, use, store, write, which can roughly be considered to be atomic in the basic data type of access reading and writing. If the scenario requires a greater atomicity guarantee, the Java memory model also provides lock and unlock, although the virtual machine does not open the lock and unlock operations directly to the user, But it provides a higher level bytecode directive Monitorenter and monitorexit to implicitly use these two operations, the two bytecode instructions reflected in the Java code is the synchronization block----synchronized keyword.

What is atomicity?

In Java, the operation of variables of the base data type is atomic, meaning that the operations are non-disruptive, either executed or not executed. See Example:

int x = ten;         // Statement 1y = x;               // Statement 2x + +;                // Statement 3x = x + 1;        // Statement 4

Which of the several statements are atomic operations?

In fact, only statement 1 is an atomic operation, and the other three statements are not atomic in nature. Statement 1 is to assign the value 10 directly to X, which means that the thread executes the statement to write the value 10 directly into working memory. Thread execution statement 2 actually contains 2 operations, it first to go to the main memory to read the value of x, and then write the value of x to the working memory, although reading the value of x and writing the value of X to the working memory of the 2 operations are atomic operations, but together is not atomic operation. Similarly, X + + and × = x+1 include 3 operations: reads the value of x, adds 1 operations, and writes a new value. so the above 4 statements only have the atomicity of statement 1 operations. that is, only a simple read, assignment (and must assign a number to a variable, the reciprocal assignment of a variable is not an atomic operation) is the atomic operation.

2. Visibility (Visibility)

Visibility means that when a thread modifies the value of a shared variable, other threads can immediately know the change. Volatile has actually written this point in detail, in fact, the Synchronized keyword is also possible to achieve visibility, the visibility of synchronized is "to perform a unlock operation on a variable, you must first synchronize this variable back to the main memory" this rule obtained. In addition, the final keyword can also achieve visibility, because the final modified field will be visible in the constructor once the initialization is complete and the constructor does not pass this out, and the value of the final field can be seen in other threads.

What is visibility?

Plain English is a thread that modifies a variable and other threads can immediately know it. ensure visibility can use the previously mentioned volatile keyword (forcing immediate write to main memory, so that other threads share variable cache row invalidation), as well as heavyweight lock synchronized (that is, synchronization between threads, unlock, before the value of the write variable back to memory, As sequential execution), and finally the constant-final modification (the other threads are visible once the initialization is complete). In fact, here can not help or add, the keyword volatile semantics in addition to ensure that different threads on the shared variable operation visibility, but also prohibit the command reordering! That is to ensure the order of.

3, order (ordering)

The natural ordering of Java programs can be summed up in one sentence: If you observe in this thread, all operations are orderly, and if you look at another thread in a thread, all operations are unnecessary . The first half of the sentence refers to the "line range expression as the semantics of walking," the latter sentence refers to "order reordering" and "working memory and main memory synchronization delay" phenomenon. The Java language provides the volatile and synchronized two keywords to ensure the ordering of operations between threads, and the volatile keyword itself contains the semantics of prohibiting command reordering, while synchronized is the " A variable that allows only one thread to lock on it at the same time "this rule provides that two synchronized blocks holding the same lock can only be entered serially.

What is Order and reordering?

Or plain English, in this thread, all operations appear to be orderly, but outside of this thread (other threads), these operations are unordered. Involves the following:

    • Command rearrangement (breaks the order between threads)
    • Previously said the work memory and main memory synchronization delay (that is, thread A has updated two variables m and N, but because of the synchronization delay between the thread working memory and the JVM main memory, thread B may not yet fully synchronize the two variables of thread a update, you may see the first n ... For b, it looks at A's operation is unordered, the order cannot guarantee).

Six, the first occurrence happens-before principle

If all the ordering in the Java memory model is done only by volatile and synchronized, then some of the operations will become cumbersome, but we do not feel this when writing Java code, because there is one in the Java language " First occurrence (Happens-before) "principle. This principle is very important, it is to judge whether the data is competitive, thread is the main basis for security, relying on this principle, we can use a few rules to determine whether there are two operations in the concurrency between the possible conflict between the problem.

The so-called antecedent principle refers to the partial order relationship between two operations defined in the Java memory model, and if operation a precedes operation B, the effect of operation A can be observed by Operation B , which includes modifying the values of shared variables in memory, sending messages, calling methods, and so on. Java memory model has some natural, do not need any synchronization aids in the pre-existing relationship:

1, program Order rules: In a thread, according to the control flow sequence, the control flow before the operation first occurs in the control flow behind the operation, said "control Flow" is because also consider the branch, loop structure.

2, the Tube lock rule: A unlock operation first occurs after the face of the same lock operation.

3. Volatile variable rule: The write operation of a volatile variable precedes the read operation of the variable.

4. Thread Start rule: the Start () method of the thread object takes precedence over each action of this thread.

5. Thread termination rule: All operations in the thread first occur on termination detection for this thread.

6. Thread break rule: the invocation of the thread interrupt () method first occurs when the code of the interrupted thread detects that the interrupt event occurred.

7. Object termination rule: Initialization of an object occurs at the beginning of its finalize () method.

8, pass the new: If the operation a first occurs in operation B, Operation B first occurs in Operation C, then operation a must first occur in Operation C.

The Java language does not need any synchronous means to ensure that the first occurrence of the rules can be established only above these amounts, if the relationship between the two is not, and can not be deduced by the following rules, they do not have the order of protection. Take an example to see:

Private int i = 0;  Public void SetI (int  i) {    this. i = i;}   Public int Geti () {    return  i;}

A very common set of getter/setter, assuming that a line enters upgradeable calls SETI (1), and the B thread calls the same object's Geti (), what is the return value of the B thread?

The rules of the first occurrence principle are analyzed in turn. Since two methods are called separately by two threads, the rules of Procedure order do not apply here, and because there is no synchronization block, there is no unlock and lock, so the pipe lock rule does not apply here; I is not modified by the keyword volatile, so the volatile variable rule does not apply here , the subsequent start, end, interrupt, and object termination are not related to this, and therefore do not apply. Because there is not a practical first occurrence rule, so the last transfer is not discussed, so transitivity also does not apply. Since all the antecedent principles do not apply, even though the SETI (1) operation of thread A first occurs in time, it is not possible to determine the return result of thread B's Geti (), in other words, the operation is not thread safe.

So how do you fix this problem? There are at least two simple ways to do this:

1, setter/getter are defined as synchronized, so you can apply enhancement locking rules

2, I is defined as a volatile variable, because the setter method changes to I do not depend on the original value of I, to meet the volatile keyword usage scenario, so you can apply the volatile variable rule

Java memory model

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.