原子性、可见性、有序性、
(1)原子性
原子性是指一个操作是不可中断的,要么全部执行成功要么全部执行失败
```javascript
Int a = 10; //原子性
a++; //1.读取a的值 2.对a+1 3.更新的值赋给a
Int b = a; //1.读取a 2.将a赋给b
a = a+1;
```
java内存模型中定义了8中操作都是原子的
- lock(锁定):作用于主内存中的变量,它把一个变量标识为一个线程独占的状态;
- unlock(解锁):作用于主内存中的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定
- read(读取):作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便后面的load动作使用;
- load(载入):作用于工作内存中的变量,它把read操作从主内存中得到的变量值放入工作内存中的变量副本
- use(使用):作用于工作内存中的变量,它把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用到变量的值的字节码指令时将会执行这个操作;
- assign(赋值):作用于工作内存中的变量,它把一个从执行引擎接收到的值赋给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作;
- store(存储):作用于工作内存的变量,它把工作内存中一个变量的值传送给主内存中以便随后的write操作使用;
- write(操作):作用于主内存的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中。
java内存模型只是要求上述两个操作是顺序执行的并不是连续执行的。
(2)有序性
public class Singleton {
private Singleton() { }
private volatile static Singleton instance;
public Singleton getInstance(){
if(instance==null){
synchronized (Singleton.class){
if(instance==null){
instance = new Singleton();
}
}
}
return instance;
}
}
使用这个双重校验锁例子说明有序性
关键在于 instance = new Singleton();
实际上这条语句包含是三个操作
1.分配对象的内存空间;
2.初始化对象;
3.设置instance指向刚分配的内存地址
但是因为重排序的问题 有可能会发生执行顺序错误
如果2和3进行重排序执行顺序变为 1 3 2
在多线程的情况下线程B先进行判断if(instance==null)会为true
实际上instance并没有初始化对于B来说并没有为对象分配空间
volatile包含禁止指令重排序的语义,其具有有序性。
(3)可见性
可见性是指当一个线程修改了共享变量后,其他线程能够立即得知这个修改。
对synchronzed内存语义进行了分析,当线程获取锁时会从主内存中获取共享变量的最新值,释放锁的时候会将共享变量同步到主内存中。
synchronized: 具有原子性,有序性和可见性; volatile:具有有序性和可见性