Volatile总结
1.Java内存模型
java内存模型中 所有变量都存储在主内存(虚拟机内存)《主要指共享变量》,每个线程有着自己独有的工作内存,工作内存中保存了该线程使用的变量,这些变量来自主内存中变量的副本拷贝。线程对变量的所有操作都必须在工作内存中进行,不能直接读写主存中的变量,不同线程之间的工作内存时相互独立的,不可以访问其他线程的工作内存。
在线程工作时,把需要的变量从主内存中拷贝到自己的工作内存
当一个线程要使用一个共享变量时,并不会直接使用,而是使用它的一个副本,然后交互副本值 ,
当出现JMM的缓存不一致时可以总线加锁 也可以使用 MESI缓存一致性协议
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fAVphV96-1616324208923)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210311155347951.png)]
java 中volatitle 就相当于使用了MESI缓存一致性
下面代码展示 volatile 的作用 -boolean类型的开关
/**
* @Author: hqx
* @Description:
* @Date: Created in 12:01 2021/3/21
*/
/**
* @author Administrator
* @create 2021-03-21 12:01
* @desc
**/
public class volatilettest {
//使用volatile 作为 boolean类型 开关
private static boolean flag1 = false;
private static volatile boolean flag2 = false;
public static void main(String[] args) throws InterruptedException {
volatilettest vo = new volatilettest();
new Thread(() -> {
//flag为false 时一直循环
System.out.println("111工作中---");
while (!flag1) {
}
System.out.println("111工作结束--");
}).start();
new Thread(() -> {
//flag为false 时一直循环
System.out.println("222工作中---");
while (!flag2) {
}
System.out.println("222工作结束--");
}).start();
//主线程
Thread.sleep(1000);
vo.change1();
vo.change2();
}
public void change1() {
System.out.println("1进入改变函数");
flag1 = true;
System.out.println("1改变完成-");
}
public void change2() {
System.out.println("2进入改变函数");
flag2 = true;
System.out.println("2改变完成-");
}
}
2.volatitle 原理实现
会在汇编语言中加入一个lock指令,该指令会将当前处理器缓存行的数据立刻写回到系统的内存中,并且这个写回内存的操作还会引起在其他cpu里缓存了该内存地址的数据无效**(MESI协议)cpu总线嗅探机制**
工作内存会与主内存进行数据交互读写,主要由8种操作进行:
lock(锁定):作用于主内存变量,把一个变量标识为一条线程独占
unlock(解锁):
read(读取):作用于主内存变量,将一个变量值从主内存传输到线程的工作内存
load(载入):作用于工作内存变量,他把通过read操作从主内存中得到的变量值放入工作内存的变量副本中
use(使用):作用域工作内存变量,将工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个要给变量赋值的字节码执行时会使用这个操作
assign(赋值):作用于工作内存的变量,它把一个从执行引擎处接收到的值赋给工作内存中的一个变量,每当虚拟机遇到一个给变量赋值的字节码时就会执行这个操作
stroe(存储):作用域工作内存变量,将工作内存中的一个变量的值传送到主内存中
write(写入):作用域主内存变量 ,他把通过store操作从工作内存中读取的变量值放入主内存的变量中
上述8个操作存在约束:
1.read+load 与 store+write 可以成对出现
2.不允许线程丢弃它最近的assign操作 ,即变量在工作内存中改变之后,必须同步写回主内存
3.不允许线程把没有经过assign操作的变量写回到主存
4.一个新的变量只能在主内存中诞生,不允许在工作内存中国使用未经初始化的变量,即在进行use 之前必须load 在store之前必须assign
5.对一个变量执行lock操作
下图为上面boolean开关的实例的一个过程演示
通过read 读取主内存中的变量并传送到工作内存,load将read获取的值赋值给工作内存中对应的变量,use读取initFlag的值给到执行引擎,assign将更新后的值写回到工作内存中的initFlag 在通过store,write写回到主内存
volatitle 会在store和write这个过程中加锁,并且在触发cpu嗅探机制
volatitle作用
在通过store,write写回到主内存
volatitle 会在store和write这个过程中加锁,并且在触发cpu嗅探机制
[外链图片转存中…(img-RzVV6eiC-1616324208947)]
volatitle作用
线程可见性,可以禁止指令重排 ,保证顺序性。不具备线程安全性,原子性