Java Memory Model-basic, java Memory Model

Source: Internet
Author: User

Java Memory Model-basic, java Memory Model
Classification of basic concurrent programming models

In concurrent programming, we need to deal with two key issues: how to communicate between threads and how to synchronize between threads (here the thread refers to the active entity of concurrent execution ). Communication refers to the mechanism by which threads exchange information. In imperative programming, there are two communication mechanisms between threads: Shared Memory and message transmission.

In the concurrency model of shared memory, threads share the public state of the program, and threads implicitly communicate through the public state in the write-read memory. In the message transmission concurrency model, there is no public state between threads, and the threads must explicitly send messages for explicit communication.

Synchronization refers to the mechanism by which a program is used to control the relative sequence of operations between different threads. In the shared memory concurrency model, synchronization is performed explicitly. The programmer must explicitly specify a method or code segment to be mutually exclusive between threads. In the message transmission concurrency model, because the message must be sent before receiving the message, the synchronization is implemented implicitly.

Java concurrency uses the shared memory model. Communication between Java threads is always conducted implicitly, and the entire communication process is completely transparent to programmers. If Java programmers who write multi-threaded programs do not understand the working mechanism of implicit inter-thread communication, they may encounter various strange memory visibility problems.

Java Memory Model Abstraction

In java, all instance domains, static domains, and array elements are stored in the heap memory, and threads in the heap are shared. (This article uses the term "shared variable" to represent the instance domain, static fields and array elements ). Local variables, method-defined parameters (formal method parameters in java) and exception handler parameters are not shared among threads, they do not have memory visibility issues, nor are they affected by the memory model.

Communication between Java threads is controlled by the Java Memory Model (JMM for short). JMM determines when a thread writes shared variables to another thread. From an abstract point of view, JMM defines the abstract relationship between the thread and the main memory: Shared variables between threads are stored in the main memory, each thread has a private local memory (local memory). The local memory stores a copy of this thread to read/write shared variables. Local memory is an abstract concept of JMM and does not exist. It covers cache, write buffer, registers, and other hardware and compiler optimizations. The Java memory model is abstracted as follows:

To communicate with thread A and thread B, follow these two steps:

The following describes the two steps:

As shown in, local memory A and B have copies of the shared variable x in the primary memory. Assume that the x value in the three memories is 0 at the beginning. Thread A temporarily stores the updated x value (assuming the value is 1) in its local memory A during execution. When thread A and thread B need to communicate, thread A will first refresh the modified x value in its local memory to the main memory. In this case, the x value in the main memory is changed to 1. Then, thread B goes to the main memory to read the updated x value of thread A. At this time, the x value of thread B's local memory is also changed to 1.

On the whole, these two steps are essentially because thread A is sending messages to thread B, and the communication process must go through the main memory. By controlling the interaction between the main memory and the local memory of each thread, JMM provides memory visibility for java programmers.

Reorder

To improve performance, compilers and processors often reorder commands when executing programs. There are three types of sorting:

From the java source code to the actual execution of the command sequence, there are three types of re-sorting:

The preceding values 1 belong to the compiler and 2 and 3 belong to the processor. These re-sorting may cause memory visibility problems in multi-threaded programs. For the compiler, the JMM compiler re-sorting rules disable specific types of compiler re-sorting (not all compiler re-sorting must be disabled ). For processor re-sorting, JMM's processor re-sorting rules require the java compiler to insert a specific type of memory barriers (memory fence) command when generating the command sequence, the memory barrier command is used to prohibit specific types of processors from being reordered (not all processors are reordered ).

JMM is a language-level memory model. It ensures that different compilers and different processor platforms prohibit specific types of compilers from being reordered and processors being reordered, provides consistent memory visibility for programmers.

Processor re-sorting and memory barrier commands

Modern processors use a write buffer to temporarily save data written to memory. The write buffer can ensure that the command line runs continuously. It can avoid the delay caused by the pause of the processor and waiting for data writing to the memory. At the same time, you can refresh the write buffer in batches and Merge multiple writes to the same memory address in the write buffer to reduce the consumption of the memory bus. Although the write buffer has so many advantages, the write buffer on each processor is only visible to the processor where it is located. This feature will have an important impact on the execution sequence of memory operations: the execution sequence of the processor's read/write operations on the memory is not necessarily the same as the actual read/write operation sequence in the memory! For details, see the following example:

Processor Processor B
A = 1; // A1
X = B; // A2
B = 2; // B1
Y = a; // B2
Initial status: a = B = 0
The result is as follows: x = y = 0.

Assume that processor A and processor B execute memory access in parallel in the program order, but eventually the result of x = y = 0 may be obtained. The specific causes are as follows:

Here, processor A and processor B can write shared variables to their own write buffer (A1, B1) at the same time, and then read another shared variable (A2, B2) from the memory ), at last, the dirty data stored in the Self-written cache is refreshed to the memory (A3, B3 ). When executed in this time series, the program can get the result of x = y = 0.

From the actual memory operation sequence, until processor A executes A3 to refresh its write cache, write operation A1 is actually executed. Although processor A executes memory operations in the order of A1-> A2, the actual memory operations occur in the order of A2-> A1. At this point, the memory operation sequence of processor A is re-ordered (the case of processor B is the same as that of processor A, so we will not repeat it here ).

The key here is that since the write buffer is only visible to the processor, it may cause the processor to execute memory operations in a different order from the actual operation sequence in the memory. Since modern processors all use the write buffer, modern processors allow reordering of write-read operations.

Below is a list of the reordering types allowed by common processors:

  Load-Load Load-Store Store-Store Store-Load Data Dependency
Iscsi-TSO N N N Y N
X86 N N N Y N
Ia64 Y Y Y Y N
PowerPC Y Y Y Y N

"N" in the cell above indicates that the processor does not allow two operations to be reordered, and "Y" indicates that re-sorting is allowed.

From the table above, we can see that common processors allow Store-Load re-sorting, and common processors do not allow re-sorting operations with data dependencies. There are relatively strong processor memory models for both the world-wide and x86 processors. They only allow the re-sorting of write-read Operations (because they all use the write buffer zone ).

※Note 1: when using the TSO (Total Store Order) Memory Model for running, the characteristics of the iSCSI processor are as follows.

※Note 2: x86 in the Table above includes x64 and AMD64.

※Note 3: The Memory Model of the ARM processor is similar to that of the PowerPC processor.

※Note 4: This document describes data dependencies.

To ensure memory visibility, the java compiler inserts memory barrier commands to prevent specific types of processors from being reordered at the proper location where the command sequence is generated. JMM classifies memory barrier commands into the following four categories:

Barrier type Command example Description
LoadLoad Barriers Load1; LoadLoad; Load2 Ensure the loading of Load1 data, which is earlier than Load2 and all subsequent loading commands.
StoreStore Barriers Store1; StoreStore; Store2 Make sure that Store1 data is visible to other processors (refresh to memory) and stored in Store2 and all subsequent storage commands.
LoadStore Barriers Load1; LoadStore; Store2 Ensure that Load1 data is loaded, and all subsequent storage commands in Store2 are refreshed to the memory.
StoreLoad Barriers Store1; StoreLoad; Load2 Make sure that Store1 data is visible to other processors (New to memory), prior to Load2 and all subsequent loading commands. StoreLoad Barriers will execute the memory access commands after all the memory access commands (storage and loading commands) prior to the barrier.

StoreLoad Barriers is a "all-inclusive" Barriers, which has three other Barriers at the same time. Most modern multi-processors support this barrier (other types of barrier are not necessarily supported by all processors ). The overhead of executing this barrier is very expensive because the current processor usually needs to refresh all the data in the write buffer to the memory (buffer fully flush ).

Happens-before

Since JDK5, java uses the new JSR-133 Memory Model (unless otherwise stated in this article, it targets all JSR-133 memory models ). The JSR-133 uses the concept of happens-before to describe memory visibility between operations. In JMM, if the result of an operation needs to be visible to another operation, there must be a happens-before relationship between the two operations. The two operations mentioned here can be within one thread or between different threads.

The following are the rules that are closely related to programmers:

  • Program sequence rules: any subsequent operations of happens-before in a thread.
  • Monitor lock rules: unlock a monitor lock. happens-before then locks the monitor lock.
  • Volatile variable rules: Write a volatile domain, and happens-before reads the volatile domain in any future.
  • Transmission: If A happens-before B and B happens-before C, then A happens-before C.

Note that there is a happens-before relationship between the two operations, which does not mean that the previous operation must be executed before the next operation! Happens-before only requires the previous operation (result of execution) to be visible to the next operation, the first operation is prior to the second operation in order (the first is visible to and ordered before the second ). The definition of happens-before is very subtle. Later, we will explain why happens-before is so defined.

Shows the relationship between happens-before and JMM:

As shown in, a happens-before rule usually corresponds to multiple compiler and processor reordering rules. For java programmers, The happens-before rule is simple and easy to understand. It prevents java programmers from learning complex re-sorting rules to understand the memory visibility guarantee provided by JMM and the specific implementation of these rules.

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.