Concurrent with the JVM

1.jvm memory model

Hardware memory model
processor - "Cache -" cache coherency protocol - "main memory

java memory model
thread "-" working memory "-" save and load "---" main memory

Interaction between java memory

(1) lock (lock): acting on the main memory of the variables, a variable state marked as an exclusive thread

(2) unlock (unlock): the role of the variables in main memory, the variable is in a locked state is released, after the release of the variables can be locked other threads

(3) read (read): variable acting on the main memory, the value of a variable transfer from main memory to the working memory of the thread, for subsequent use load operation

(4) load (load): copy of the variable acting on the variable working memory, which is obtained in the variable read from main memory into the working memory of the value
(5) use (use): a variable acting on the working memory , the working memory of a variable value passed to the execution engine

(6) assign (assignment): influencing variables in the working memory, which is received from the execution engine to a value assigned to a variable working memory

(7) store (store): the role of working memory variables, the value of a variable of the work memory is transferred to the main memory, for subsequent write operation

(8) write (writing): acting on the main memory variable, which is transmitted from the store operation variable values ​​of a working memory to the main memory variable

8 the above operations must satisfy the following rules

1, does not allow read and load, store one and write operations occur alone, which does not allow a variable read from the main memory but not working memory access
by, or written back to memory from the work initiated by the main memory but does not accept the situation appear.

2, does not allow one thread to discard its most recent assign operation that changed the variables in the working memory after the change must be synchronized back to main memory.

3, no reason to not allow a thread (not assign any action occurs) the data from the working memory thread synchronization back to main memory.

4、一个新的变量只能在主内存中“诞生”,不允许在工作内存中直接使用一个未被初始化(load或assign)的变量,换句话说,就是对一个变量实施use、store操作之前,必须先执行过了assign和load操作。

5、一个变量在同一时刻只允许一条线程对其进行lock操作,但lock操作可以被同一条线程重复执行多次,多次执行lock后,只有执行相同次数的unlock操作,变量才会被解锁。

6、如果对一个变量执行lock操作,那将会清空工作内存中此变量的值,在执行引擎使用这个变量前,需要重新执行load或assign操作初始化变量的值。

7、如果一个变量事先没有被lock操作锁定,那就不允许对它执行unlock操作,也不允许去unlock一个被其他线程锁定住的变量。

8、对一个变量执行unlock操作之前,必须先把此变量同步回主内存中(执行store、write操作)。

2.先行发生原则 happens-before

判断数据是有有竞争、线程是否安全的主要依据

1.程序次序规则:同一个线程内,按照代码出现的顺序,前面的代码先行于后面的代码,准确的说是控制流顺
序,因为要考虑到分支和循环结构。

  1. 管程锁定规则:一个unlock操作先行发生于后面(时间上)对同一个锁的lock操作。

  2. volatile变量规则:对一个volatile变量的写操作先行发生于后面(时间上)对这个变量的读操作

  3. 线程启动规则:Thread的start( )方法先行发生于这个线程的每一个操作。

  4. 线程终止规则:线程的所有操作都先行于此线程的终止检测。可以通过Thread.join( )方法结束、
    Thread.isAlive( )的返回值等手段检测线程的终止。

  5. 线程中断规则:对线程interrupt( )方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可
    以通过Thread.interrupt( )方法检测线程是否中断

  6. 对象终结规则:一个对象的初始化完成先行于发生它的finalize()方法的开始。

  7. 传递性:如果操作A先行于操作B,操作B先行于操作C,那么操作A先行于操作C。

    为什么要有该原则?
     无论jvm或者cpu,都希望程序运行的更快。如果两个操作不在上面罗列出来的规则里面,那么就可以对他们进行任意的重排序。
     时间先后顺序与先行发生的顺序之间基本没有太大的关系。

3.指令重排序

什么是指令重排序?

重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段。

数据依赖性

编译器和处理器在重排序时,会遵守数据依赖性,编译器和处理器不会改变存在数据依赖关系的两个操作的执
行顺序。(仅针对单个处理器中执行的指令序列和单个线程中执行的操作,不同处理器之间和不同线程之间的
数据依赖性不被编译器和处理器考虑。)
两操作访问同一个变量,其两个操作中有至少一个写操作,此时就存在依赖性
写后读 a=0 b=a
读后写 a=b b=1
写后写 a=1 a=2 a=1,b=1
写后读 a=0 b=a 正确b=0 错误b=1

as-if-serial原则

不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变。
x=0,y=1

x=1, y=0

x=1, y=1

x=0, y=0

public class Demo2 {

    static  int x = 0, y = 0, a = 0, b = 0;

    public static void main(String[] args) throws InterruptedException {

        int i = 0;
        boolean flag = true;
        while (flag) {
            i++;

            Thread thread = new Thread(() -> {
                a = 1;
                x = b;
            });


            Thread thread1 = new Thread(() -> {
                b = 1;
                y = a;
            });

            thread.start();
            thread1.start();
            thread.join();
            thread.join();


            System.out.println(
                    "第" + i + "次的值:" + "x=" + x + " y=" + y
            );


            if (x == 0 && y == 0) {
                flag = false;
            } else {

                x = 0;
                y = 0;
                a = 0;
                b = 0;
            }

        }

    }

}

Guess you like

Origin www.cnblogs.com/charlypage/p/10962592.html
JVM
JVM