Java Memory model and multithreading

Source: Internet
Author: User

Modern computer, CPU in computing, not always read from memory, its data reading order priority is: Register-cache-memory, thread computing time, raw data from memory, in the calculation process, some data may be read frequently, the data is stored in registers and cache, When the thread is finished, these cached data should be written back to memory at the appropriate time, and when multiple threads read and write some memory data at the same time, because of the visibility of the data involved, the order of the operation, so it will produce multi-threaded concurrency problems.

Java as a platform-independent language, JLS (Java language Specification) defines a unified memory management model JMM(Java memory model), JMM masking the underlying platform memory management details, in a multithreaded environment must solve the problem of visibility and order. The JMM specifies that the JVM has main memory and working memory (working memory), all class instances, static data, and so on, which are shared by multiple threads. While working memory is the variable that the thread copies from the main memory and the local variables obtained by the access method, the other threads that are private to each thread are inaccessible, and each thread operates on the variable by copying it from main memory to working memory and then manipulating it. Data communication between multiple threads cannot be communicated directly to each other, only through shared variables.

JLS defines the operation instruction of the thread to main memory:read,load,use,assign,store,write. These behaviors are non-decomposed atomic operations, relying on each other, read-load from the main memory to the current working memory, use-assign executing code to change the shared variable value, store-write with working memory data to refresh main memory related content.

The thread is referencing a variable, if the thread is working in memory without that variable, copying a copy from main memory to working memory through Read-load, the thread references that copy when the same thread references the variable again, and it is possible to retrieve the variable copy from memory again (read-load-use ), it is also possible to refer directly to the original copy (use), which means that the read, load, and used order can be determined by the JVM implementation system.

When a thread writes a variable, it assigns the value to a copy of the variable in the working memory (assign), and the copy of the variable is synchronized to main memory (Store-write) when it is completed, i.e. the assign,store,write sequence is determined by the JVM implementation system.

The sequential operation of multithreading on main memory may lead to concurrency problems, see an example:

Class test{    int i = 0;    

Premise: Thread A, b use the same instance of class Test, execute order 1-6

    1. Thread A reads I copy x from main memory to working memory with x value of 0
    2. Thread B reads I copy y from main memory to working memory with a Y value of 0
    3. Thread A adds X 1 to working memory and X value to 1 in working memory
    4. Thread A commits X to main memory, I becomes 1 in main memory
    5. Thread B adds 1 to the working memory, and the Y value in working memory becomes 1
    6. Thread B commits y to main memory, I becomes 1 in main memory

* Single-threaded environment, I to two times plus 1, the result must be 2, but in a multithreaded environment, I two times plus 1, the result is not necessarily 2, depending on the order of execution of the 2nd and 4th steps in the previous example!

volatile is a synchronization method provided by Java, but it is a lightweight synchronization, why so, because volatile can only guarantee the multi-threaded memory visibility, does not guarantee the execution of multi-threaded order. And the most thorough synchronization to ensure the order and visibility. When the same thread repeatedly assigns a value to a field, it is possible that the threads will only assign to the copy in the working memory until the last assignment is made to the primary store. Any variable that is modified by volatile does not copy the copy to the working memory, and any changes are written in memory in time. As a result, changes to Valatile modified variables are immediately visible to all threads, but volatile does not guarantee that changes to variables are ordered. For the volatile variable to provide ideal thread safety, the following two conditions must be met:

1, the write operation to the variable does not depend on the current value.

2. The variable is not included in the invariant with other variables.

Examples of errors:

Class volatilefalse{       int i;    void Add () {i++;}} 

Note: Although volatile guarantees the modification of I "in Time" written in main memory, all threads can see immediately, but i = i + 1 to the variable I write operation depends on the current value, and the current value is variable, because the value of read and write I under multithreading is unordered, So the final value to I after multiple threads running the same instance of Volatilefalse is not necessarily correct.

The right example:

Class volatiletrue{    int i;    void SetI (   

Note: There is no volatie declaration, in a multithreaded environment, the value of I is not necessarily correct, because this.i = J; involves assigning a value to I and synchronizing the value of I with the steps of main memory, this order may be disrupted. If it is declared with Volatie, it is thread-safe to read the main memory copy to the working RAM and to synchronize the steps of I to main storage, which is equivalent to an atomic operation.

Volatile is suitable for this scenario: A variable is shared by multiple threads, and the thread assigns a value directly to the variable. This is a very simple synchronization scenario where the cost of using volatile is very small.

synchronized keyword as one of the guarantee means for the execution order of multithreaded concurrency environment, if a thread accesses a method identified as synchronized and operates on the corresponding variable, then according to JLS, The JVM performs the following steps:

    1. The object lock is obtained (the lock of the normal method is the this object, and the static method is the class object of the classes) and locks it (lock).
    2. Copies the required data from the main memory to its own working memory (read and load).
    3. Read or modify the corresponding variable value (use and assign) according to the program flow.
    4. Copy the variable that modifies the value in your working memory back to main memory (store and write).
    5. Releases the object lock (unlock).

Some summary of the synchronized:

PublicClass test{Publicvoid Method0 () {...}PublicSynchronizedvoid Method1 () {...}Publicvoid Method2 () {Synchronized (this) {...} } public void method3 (Someobject so) {synchronized (SO) {...}} public void method4 () {... private byte[" lock = new    byte[0];    synchronized (lock) {...} ... } public synchronized  static void method5 () {...} public void Method6 () {class) {...}}}         
    1. Method1 synchronization function and method2 in sync block synchronized (this) {...} The acquired synchronization locks are instance objects of class test, that is, object locks, so the method1 and method2 effects are equivalent.
    2. When multiple concurrent threads access a synchronization function or a synchronization block in the same object, the thread that acquires the lock of the object is executed, while the other thread that accesses the object's synchronization function or synchronization block (whether or not the same synchronization function or synchronization block) will block until the object lock is acquired. Of course, the thread that accesses the object's non-synchronous method or synchronization block is not restricted by the object lock and can be accessed directly.
    3. METHOD2 Sync block Synchronized (this) {...} In this refers to the object that calls this method, if the two threads are called T1 and T2 (instantiation of class test) two objects, then this synchronization block for these two threads is invalid, you can use METHOD3 in the synchronization block synchronized (SO) {...} To hang the lock on top of other objects.
    4. What if you want to synchronize some of the code in a function? METHOD4 is implemented with a special instance variable acting as a lock.
    5. Method5 static sync function and Method6 in sync block synchronized (test.class) {...} The acquired synchronization lock is a class lock, which is the lock of class test, not the object lock of class test.
    6. Because class locks and object locks are different locks, method1 and method5 do not constitute synchronization in multi-threaded concurrency environments.

Java Memory model and multithreading

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.