jvm内存模型

https://www.cnblogs.com/liclBlog/p/9379767.html

补充:

可见性

 个线程修改了变量,其他线程可以立即知道

保证可见性的方法

- volatile

- synchronized (unlock之前,写变量值回主存)

- final(一旦初始化完成,其他线程就可见)

有序性

在本线程内,操作都是有序的

在线程外观察,操作都是无序的。(指令重排 或 主内存同步延时)

指令重排

– 线程内串行语义

              •写后读  a = 1;b = a;  写一个变量之后,再读这个位置。

              •写后写  a = 1;a = 2;  写一个变量之后,再写这个变量。

              •读后写  a = b;b = 1;  读一个变量之后,再写这个变量

              •以上语句不可重排

              •编译器不考虑多线程间的语义

可重排: a=1;b=2;

指令重排会破坏程序间的有序性

class OrderExample {
int a = 0;
boolean flag = false;

public void writer() {
    a = 1;                   
    flag = true;           
}

public void reader() {
    if (flag) {                
        int i =  a +1;      
        ……
    }
}
}

线程A首先执行writer()方法,线程B线程接着执行reader()方法 ,线程Bint i=a+1 是不一定能看到a已经被赋值为1

因为在writer中,两句话顺序可能打乱。

线程A可能是

flag=true

a=1

线程B可能是

flag=true(此时a=0)

防止指令重排的方法是保证线程的安全

指令重排的基本原则

– 程序顺序原则:一个线程内保证语义的串行性

– volatile规则:volatile变量的写,先发生于读

– 锁规则:解锁(unlock)必然发生在随后的加锁(lock)前

– 传递性:A先于B,B先于C 那么A必然先于C

– 线程的start方法先于它的每一个动作

– 线程的所有操作先于线程的终结(Thread.join())

– 线程的中断(interrupt())先于被中断线程的代码

– 对象的构造函数执行结束先于finalize()方法

解释运行

– 解释执行以解释方式运行字节码

– 释执行的意思是:读一句执行一句

编译运行(JIT

– 将字节码编译成机器码

– 接执行机器码

– 行时编译

编译后的性能有数量级的提升。

原文地址:https://www.cnblogs.com/liclBlog/p/15349558.html