Reading notes | Java memory model with thread

Disclaimer: This article is a blogger original article, please indicate the source: https://blog.csdn.net/qq_38182125/article/details/90740873

I. Overview

This article is based on "in-depth understanding of the Java Virtual Machine," a book of reading notes for the Java virtual machine memory model of concurrency and threads made the introduction, the content of this article belong to refine the text of the article structure is as follows:

  • Before the official start of appetizers
  • Java Memory Model
  • From the perspective of the virtual machine to see thread

Second, before the official start of appetizers

1. Necessity of multi-tasking

In modern multi-tasking computer operating system is almost a necessary function. Let the computer do several things at the same time the following factors:

  • Now more and more powerful computing power.
  • Computer's processing speed and its storage and communication sub-rate gap is too large, strong computing power of the processor has to wait a long time in the state resulted in a waste of resources, multitasking can make more effective use of these idle processing device.
  • Easy server to provide services to multiple clients. Number of transactions per second (Transactions Per Second, TPS) is an important indicator for measuring server performance is good or bad, has a close relationship with its program of concurrent capacity.

2. Hardware efficiency and consistency

Concurrency problems with concurrency issues in the physical computer Java virtual machine has a high similarity, physical opportunities and solutions to the problem, we can do the next text reference

  • Concurrent purpose : to make a computer perform several concurrent computing tasks, thereby enhancing the performance of computer processors.
  • Problem : the vast majority of computing tasks can not be completed only by the processor, at least to interact with the processor memory, such as a data read operation, store calculation results, the IO operations are difficult to eliminate. But in a computer storage device CPU speed gap of several orders of magnitude.
  • Solution copy adding a layer of read and write speed processor speed as close as possible to tell the cache as a buffer between the memory and the processor, the operation requires the use of data to the cache, so that operation can quickly: When in operation after the end of sync back from the cache memory. Such processor without waiting for slow memory read and write.
  • It has brought new problems : cache coherence (Cache Coherence). In a multiprocessor system, each processor has its own cache, but they are also sharing the same main memory (Main Memory). When multiple processor computing tasks are related to the same piece of main memory area, it will lead to inconsistent respective cache data, then sync back to the main memory of the time, will result in data inconsistency.
  • Solution : To solve the problem of inconsistency of data, each processor will need to follow some protocol to access the cache, such agreements have MSI, MESI, MOSI (Illinois Protocol ), Synapse, Firefly and Dragon Protocol and so on.

Therefore, in the modern computer, the processor, cache and main memory diagram below:
Here Insert Picture Description


Three, Java Memory Model

Define Java memory model (Java Memory Model, JMM) the purpose of :

Block out a variety of hardware and operating system differences in memory access, in order to achieve let Java programs in a variety of platforms to achieve the same effect memory access.

1. main memory and working memory

Java memory model memory divided into separate memory and working memory, as shown below:
Here Insert Picture Description
As can be seen Java memory model and the physical model memory unit having a comparable very high, which is characterized as follows:

  • Each thread has its own working memory, working memory thread holds a copy of a copy of main memory to be used by the thread of variables.
  • Thread all operations on variables (reading, assignments, etc.) must be in working memory, but can not directly read and write the main variables in memory.
  • Direct access also work the other variables in memory between different threads, pass variable values ​​between threads are required to complete the main memory.

Note that variable and variable here say Java programming is different, it includes instance fields, static fields and elements that make up an array of objects, but does not include local variables and method parameters, because the latter is thread-private, It will not be shared.

2. Memory interactions between

Java memory model defines the following eight kinds of operations are performed between the main memory and the particular working memory of the interactive protocol, must ensure that these eight virtual machine operations are implemented atoms, can not be divided :

operating Role of the object effect
lock (lock) The main variables in memory To a variable identified as a thread exclusive state
unlock (unlock) The main variables in memory The variable is in a locked state is released, after the release of the variables can be locked other threads
read (read) The main variables in memory The value of a variable from the main memory to the working memory of the thread, for subsequent use load operation
load (load) Working memory variables Obtained in the variable read from the main memory to the copy of the variable values ​​into the working memory
use (use) Working memory variables Passes the value of memory to perform a variable engine, this operation will be performed whenever a virtual encounters a bytecode instructions need to use variable
assign (assignment) Working memory variables Received from the execution engine to a value assigned to a variable working memory, to perform this operation every time the bytecode instructions to a virtual opportunity assigned to the variable
store (storage) Working memory variables The value of a variable working memory is transferred to the main memory, for subsequent write operations using
wriite (write) The main variables in memory The obtained value of the variable store operation from the working memory into the main memory variable

To a variable copy from main memory into the working memory, to perform a read operation and load sequence, if we want the variable sync back to main memory from the working memory, store and write operations to be performed sequentially. Between two consecutive operations may not be executed sequentially. At the same time, for example, read from the main memory two variables A and B into the working memory, the sequence may be read A, read B, load B, load A.

Implement the eight basic operations must satisfy the following rules:

  • read and load, store one and write operations are not allowed alone.
  • A thread is not allowed to discard its most recent assign operation, ie, after variable changes in the working memory necessary to synchronize the changes back to main memory.
  • No reason to not allow a thread (not assign any action occurs) the data from the working memory thread synchronization back to the main memory.
  • Only the birth of a new variable in main memory, not allowed to use a variable that has not been initialized directly in the working memory.
  • A variable at the same time allowing only one thread operating its lock, but lock operation can be repeated multiple times with a thread, after repeatedly lock, unlock will only perform the same number of unlock operation variables.
  • If you do lock operation on a variable, it will clear the value of this variable working memory before the execution engine to use this variable, we need to re-execute or assign value load operation initialized variables.
  • If a variable not previously been locked lock operation, then it is not allowed to perform unlock operation is not allowed to unlock a locked variable other threads to live.
  • Before performing the unlock operation on a variable, the variable must first sync back to main memory (execution store, write operation).

3. The characteristics of Java memory model

Java memory model is built around the process of how to handle concurrency atomicity, visibility and ordering of these three features to build, the following is a detailed description of them:

  • Atomicity (Atomicity): an operation executed either perform or not.
    • Directly by the Java memory model to ensure atomicity operation variables include read, load, assign, use, store and write, we believe that the basic data types generally read and write access is provided atomic * (long, except for double).
    • Java memory model is also provided to lock and unlock guarantee atomicity guarantees a wider range of these two instructions are not open to the user, but provide a higher level of missing bytecode monitorenterand monitorexitto implicitly use two operations , these two Java bytecode instruction code is reflected to the synchronizedkeywords, so the synchronizedoperation block is also provided atomicity.
  • Visibility (Visibility): When a thread changes the value of shared variables, other threads can be aware of this change immediately.
    • Java memory model by modifying the value of the variable after the new sync back to main memory before the variable values ​​are read from the main memory to refresh the variables that depend on the main memory as a way to transfer media to achieve visibility, the following three ways:
      • volatile: the volatile by special rules to ensure that the new values ​​can be synchronized to the main memory immediately, and immediately refresh from main memory before each use. So volatile multi-threaded to ensure the visibility, common variable operation variables can not guarantee this.
      • synchronized: Visibility sync block is composed of "before performing the unlock operation on a variable, this variable must be synchronized back to the first main memory" rule obtained.
      • final: The final key field is modified once initialization is complete in the constructor, and the constructor did not "this" reference pass out, it will be able to see the value of final field in the other thread.
  • Orderliness (Ordering): observed in this thread, all operations are ordered; observed another thread in a thread, all of the operations are disordered.
    • This difference is due primarily reordering instructions and synchronous delay working memory and main memory. Java provides a guarantee orderly operation between the threads of two ways:
      • volatile: the volatile keyword may prohibit instruction reordering optimization.
      • synchronized: in the sync blocks, at the same time allowing a variable one thread only its lock operation.

4. The principle of first occurrence

First occurrence of a partial order relationship between the two operations defined in Java memory model, the data is used to determine whether there is competition, whether the thread safety of the main basis. Java Memory Model following are some "natural" advance a relationship:

  • Rule program sequence (Program Order Rule): in a thread, according to a program order of the code book EDITORIAL write operation occurs after the first operation.
  • Tube-lock rules (Monitor Lock Rule): a first unlock operation of the lock with a lock on the rear face of the operation occurred.
  • volatile variable rules (Volatile Variable Rule): write to a volatile variable first occurred in the face of this variable after the read operation.
  • Thread start rule (Thread Start Rule): start Thread object () method first occurrence in this thread every movement.
  • Thread terminates rules (Thread Termination Rule): All operations are ahead of thread termination occurs in the detection of this thread.
  • Thread break the rules (Thread Interruption Rule): calling thread interrupt () method first occurred in the interrupted thread code detection to interrupt event occurs.
  • End of rule objects (Finalizer Rule): completion of initialization of an object begin to occur ahead of its finalize () method.
  • Transitivity (Transitivity): if the operation occurs ahead A Procedure B, B ahead operation occurs in operation C, the operation with the first A operation C.

example:

public class Demo {

    static class Value{
        private int value = 0;

        public int getValue() {
            return value;
        }

        public void setValue(int value) {
            this.value = value;
        }
    }

    public static void main(String[] args) {

        Value v = new Value();
        
        Thread A = new Thread(() -> {
            v.setValue(1);
        });
        
        Thread B = new Thread(() -> {
            System.out.print(v.getValue());
        });
        
        A.start();
        B.start();
    }
    
}

Print result of this procedure is uncertain and may be 0, 1 is also possible. According to analysis of eight major rules one by one first occurred:

  • Program sequence rules : Due to operational assignments and the value is not in the same thread, so the rule does not apply.
  • The tube locking rules : Method two threads are not called sync blocks, so suited.
  • volatile variable rules : do not use the keyword volatile variable value modification, the same does not apply.
  • Thread starts, terminates, rules and object finalization rules : cases and these rules does not matter, so do not apply.
  • Transitive : because there is a suitable relationship with the first occurrence of the above rules appear, so this rule is not applicable.

in conclusion:

  1. Above starting first principles are not used in this code, so this operation is thread safe.
  2. A first operation occurred on time does not mean that this operation will first take place.

Solution:

  1. For the setter and getter methods were modified with the synchronized keyword, so that we comply with the code on the tube locking rules.
  2. Because here setter method does not depend on changes to the value of the value of the original value, so use the volatile keyword modified variable value to ensure the same thread-safe, then this program will meet the volatile variable rules.

Note: there is no significant relationship between the basic principle of chronological order and advance occur in concurrent security measure is not to receive interference chronological order, all to take place in order to advance the principles prevail.


Fourth, from the point of view of virtual machine thread

1. Thread achieved in three ways

  • Kernel threads to achieve
    • Kernel threads (Kernel-Level the Thread, KTL) : directly by the operating system kernel (Kernel) support threads.
    • Principle : kernel kernel thread is switched from the complete thread, the kernel thread scheduling by manipulating the scheduler (Scheduler), and is responsible for mapping each thread to the task processor. Each kernel thread can be regarded as a spare kernel. Programs generally do not directly use the kernel threads, but the use of lightweight processes.
    • LWP (Light Weight Process, LWP) : the usual sense talking about threads, each lightweight process consists of a kernel thread support, and kernel threads is between 1: 1 relationship.
      • Advantage : With support for kernel threads, each lightweight process can become an independent scheduling unit, even if there is a lightweight processes blocked in a system call, it will not affect the whole process to work.
      • Drawback : Since the realization of kernel threads, create, destructors and thread synchronization operations need to be based on the cost of the more expensive system calls, so the lightweight process consumes some kernel resources, while a limited number of lightweight processes.
    • Lightweight processes and kernel threads are one of the relationship, as shown below:
      Here Insert Picture Description
  • User thread implementation
    • User thread (the User the Thread, UT) : entirely on user space threads library, the kernel can not perceive implement threads exist.
    • Advantages : the establishment of user threads, synchronization, destruction and scheduling done entirely in user mode, the kernel does not consume resources, so the operation is very fast and low consumption; can support a larger number of threads.
    • Drawback : All operations require the user to program thread deal with their own problems to create threads, switching and scheduling need to be considered; processing such as "how to deal with obstruction", "multi-threaded processor system will be mapped to other processors." such issues extremely difficult, even impossible.
    • Between the user threads and processes for the 1: N relationship, as shown below:
      Here Insert Picture Description
  • User threads, plus lightweight hybrid implementation process
    • Mixed implementation-defined : implementation will be used with kernel threads and user threads, there is both user threads, there are also lightweight processes.
    • Advantage : the user thread or completely built in user space, thus creating a user thread, switches, destruction and other operations are still cheap, and can support large-scale user concurrent threads. The LWP is as a bridge between user threads and kernel threads, which can take advantage of features provided by the kernel thread scheduling and processor mapping, and user thread system calls to accomplish through lightweight threads, the entire process has been greatly reduced completely blocked risk.
    • The number of user threads and lightweight processes mixing ratio achieved is uncertain, is N: M relationship, i.e. thread-many model, as shown below:
      Here Insert Picture Description

2. The implementation of the Java threads

  • Before JDK1.2, it is based on the way the user thread implementation;
  • In JDK1.2, the threading model to implement an operating system to replace the native threads model;
  • 目前的 JDK 版本答案是不确定。在不同的平台上,Java虚拟机对于线程的实现都是不同的,因为不同的操作系统所支持的线程模型不同,而线程模型很大长度上决定了 Java虚拟机的线程是怎么映射的。线程模型只对线程的并发规模和操作成本产生影响,对 Java程序的编码和运行来说,这些差异都是透明的。

3. Java线程调度的两种方式

  • 同式线程调度(Cooperative Threads-Scheduling)
    • 原理:线程的执行时间由线程本身来控制,线程把自己的工作执行完之后,要主动通知系统切换到另一个线程上。
    • 优点:实现简单,并且切换操作对线程自己是可知的,不存在线程同步的问题。
    • 缺点:线程执行时间不可控,如果有线程一直不告知系统进行线程切换,那么程序会一直阻塞在那里。
  • 抢占式线程调度(Preemptive Threads-Scheduling)
    • 原理:线程通过系统来分配执行时间,线程的切换不由线程本身决定。Java 采用的线程调度方式就是抢占式线程调度。
    • 优点:线程的执行时间是系统可控的,不会存在一个线程导致整个进程阻塞的问题。

由于 Java的线程调度是由系统自动完成的,理论上线程是不可控的。但我们可以通过给系统某种暗示来给某些线程多一些执行时间,另外一些线程则可以少分配一点——这项操作可以通过设置线程优先级来完成。

但是线程优先级并不是太靠谱,因为Java的线程是通过映射到系统的原生线程上来实现的,所以线程的调度最终还是取决于操作系统。虽然现在很多操作系统都提供了线程优先级的概念,但是并不见得与Java线程的优先级一一对应。例如对于优先级比Java线程少的系统,就不得不出现几个优先级相同的情况了。

4. 线程的五种状态

  • 新建(New):创建后尚未启动的线程处于新建状态。
  • 运行(Runnable):包括了操作系统线程状态中的 Running 和 Ready,处于此状态的线程有可能正在执行,也有可能正在等待 CPU 为其分配时间片。
  • 无限期等待(Waiting):该状态下的线程不会被分配 CPU 执行时间,需要等待被其他线程显示唤醒。可通过下列方法让线程进入无限期等待状态:
    • 没有设置 Timeout 参数的 Object#wait() 方法。
    • 没有设置 Timeout 参数的 Thread#join() 方法。
    • LockSupport.park() 方法。
  • 限期等待(Timed Waiting):该状态下的线程同样不会被分配 CPU 执行时间,但在一定时间之后它们会由系统自行唤醒。可通过下列方法让线程进入限期等待状态:
    • Thread.sleep() 方法
    • 设置了 Timeout 参数的 Object#wait() 方法。
    • 设置了 Timeout 参数的 Thread#join() 方法。
    • LockSupport.parkNanos() 方法。
    • LockSupport.parkUntil() 方法。
  • Blocked (Blocked) : the thread is blocked state is waiting to acquire an exclusive lock, when the program is waiting to enter the synchronized block, the thread is in this state.
  • End (Terminated) : terminated thread thread state, the thread has completed execution.

Switching the state between the threads as shown below:
Here Insert Picture Description


V. REFERENCE

Reference this article from:

  • "In-depth understanding of the Java Virtual Machine"
    • Part V efficient concurrent
      • Chapter 12 Java memory model with thread

EBook resources:

Links: https://pan.baidu.com/s/1SDginxQBu90hvPeG_85epw
extraction code: bftc


I hope this article helpful to you ~

Guess you like

Origin blog.csdn.net/qq_38182125/article/details/90740873