Multithreading Basics (a) - Java Memory Model

  To better understand the Java inner model, we need to simply recall CPU cache model.

CPU Cache Cache

  In the computer, although the computing speed of the CPU to calculate quickly, but the vast majority of computer tasks can not rely on the CPU to complete. Also you need to include data interaction with an inner layer, read and write, memory element calculation results and the like. However, due to computer storage devices and the CPU operation speed gap has several orders of magnitude, modern computers usually add a layer between the read and write speeds of memory devices as close as possible and the CPU processing speed CPU caches for operation copy the required data into the cache, so that operation can be performed rapidly after the end of the operation when flushed from the cache to the main memory, so there is no need to wait for the slow CPU read and write the inner layer.

  Although the storage cache interaction of a good solution to the contradiction processor speed and memory, but it also introduces a new contradiction: memory consistency problems. When multiple processor computing tasks are located and the same piece of main memory area, it will lead to memory consistency issues, in order to solve this problem, each time the processor accesses the cache will need to follow some rules to maintain data consistency . These rules are named experts to cache coherency protocol. One of the most famous is the Intel MESI protocol. MESI protocol to ensure that each shared variables used in the cache copies consistent. General idea is: during CPU operation data in the cache, if it is found that the variable is a shared variable, which means that there is a copy of the variable in another cache, then they would do the following:

    1) reading operation, without any treatment, may directly read the data in the cache to the CPU registers;

    2) a write operation, signal the other cache, a copy of this variable has been set aside, if the variable to be read, must be read into main memory the new value.

  In addition to increasing the cache, the processor for calculating the internal unit can be fully utilized as much as possible, the processor might enter the order execution code optimized, while ensuring that the overall result of the calculation results with the code in a logical sequence of code execution is consistent. Out of order execution and optimization of CPU similar, Java virtual machine time compiler has a similar instruction reordering (Instruction Reorder) optimization.

Java Memory Model

  Java memory model (Java Memory Model, JMM) defines the interaction details of the Java virtual machine to work with the computer's main memory. I.e., the variable stored in the JVM and removed from the low-level details of such a variable memory in memory. Variables here include the instance fields, static fields and an array of objects, that is, data can be shared. Does not include local variables and method arguments, because they are the thread private and will not be shared, there would be no competition exists. JMM defines an abstract relationship between the thread and the main memory, as follows:

  1) variable is stored and shared main memory, each thread can access, where the main CPU cache memory can be compared models of main memory, but here is only part of the virtual machine memory.

  2) Each thread has its own private memory, called local memory, CPU cache model can be compared in the cache.

  3) working memory can store copies of shared variables that thread.

  4) Thread all operations on variables (read, write) are performed in the work memory, the main memory can not be directly operating variables.

  5) between different threads can not directly access the working memory of the other variables, the variable value passed between threads are required to complete the main memory.

  Learn the Java memory model can learn for our future multi-threaded, to lay the foundation valatile keywords.

 

  In concurrent programming, there are three essential characteristics, namely atomicity, ordering and visibility. We look at how to ensure the JMM these three characteristics.

JMM and Atomicity

  Atomicity means that all steps included in one operation, either all executed or not executed full. This concept can be compared in a relational database consistency of things.

In Java, the basic data types and reading a reference type variable, assignment is atomic. However, several operations are atomic composition together, it is not necessarily of the atoms. For example, the following common increment operator: 

and ++

  This statement is actually made from a combination of three operations:

  1) performs thread reads the value of y (y if a copy already in the working memory in the execution of a thread, directly acquired) from the main memory, a copy of which is then stored in the working memory of the current thread;

  2) the execution thread for the y plus perform an operation;

  3) the value of y into the main memory refreshed.

  JMM only guarantee the basic reading and atomic assignment, the other not guarantee, if you want to get some code atomicity, you can use the synchronized keyword will learn later, or in the JUC lock.

 

JMM and visibility

  Visibility refers to a program for a shared variable is modified, other threads can immediately know this change. JMM by modifying the variable values ​​after a new synchronization back to main memory before the new variable into the variable value is read from the brush main memory, such as main memory dependent manner transfer medium to achieve visibility. Java provides many ways to ensure the orderly:

  1) Use the volatile keyword, when a variable is modified volatile, read operations to the shared resources will be (of course, will be flushed to the working memory) directly in the main memory, the shared resources for the write operation will first modify working memory, the value is then immediately flushed to main memory.

  2) the use of the synchronized keyword, synchronized keyword to ensure that only one thread at the same time acquire the lock, and then perform synchronization method, shared variables to operate. And will ensure that before the lock is released, will be to change the variable flushed to main memory.

  3) using an explicit lock lock JUC provided, similar to the role and the synchronized keyword, but compared with the synchronized keyword, more lightweight.

 

JMM and ordering

  In the JMM, allows the compiler and the CPU instruction reordering, i.e. stresses in the CPU cache out of order execution and instruction reordering optimization optimization. In the single-threaded case, whatever you want to optimize how, no problem, but for multithreading, instruction reordering may cause errors. JMM has some natural ordering rules, without any display of synchronization means you can keep things in order (in fact, I believe the underlying synchronization means is used), this rule is Happens-before principles, such as

  Start rules of procedure: Tread start method prior to any actions of the thread, the thread can only truly run after the start, otherwise it is just an object.

  End of rule objects: the completion of a first object initialization occurs before fanalize method.

  Blocking rule: a first unlock operation to occur in the operation of the lock with a lock.

  传递规则:Happens-before 原则具有传递性。

如果一个操作无法从 Happens-before 原则推导出来,那么就无法保证有序性。

  与保证可见性一样,也可以使用 volatile 关键字、synchronized 关键字、JUC 提供的显式锁lock来保证有序性。其中 synchronized 保证有序性是利用“同一时间只有一个线程获得锁,然后执行同步方法,对共享变量进行操作”的这一特点来保证有序性;而 volatile 则直接暴力的禁止编译器和 CPU 的任何指令重排序,因此保证了有序性。

 

  在了解了 JMM 模型之后可以更方便学习多线程知识,特别是在后面学习 volatile 关键字的时候就会显得得心应手。

 

Guess you like

Origin www.cnblogs.com/dogeLife/p/11391863.html