什么是volatile?
------------ volatile 是一个关键字,修饰变量(共享变量)。
volatile作用
------------对于修饰的变量,确保共享变量能被准确和一致地更新,通俗的理解就是多线程情况下,别的线程对共享变量的修改,当前线程也能及时获取到最新值。
例如------代码举例:
public static boolean run = true;
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
while(run) {
}
},"t1").start();
Thread.sleep(1000);
run=false;
}
通过代码,可以看出当前存在两个线程分别是 main,t1。而对于t1线程是不断的运行,在主线程修改run值来停止t1线程。通过运行编译,来判断t1线程是否获取主线程的run=false值.
编译结果:
可以看出t1线程是RUNNABLE,也就是没有获取主线程的run值。
解决方法就是,将run方法的值用关键字volatile修饰。
实现原理
----------- 即是内存屏障实现。
–内存屏障,其实是汇编指令。
即保证在
读操作指令前加一个指令,保证数据的实时性
写操作指令后加一个指令,保证数据能及时修改回主存。
–汇编指令 Lock前缀指令:
- 将当前处理器的缓存写回主存
- 将其他线程的缓存行失效
这里的缓存行就如同操作系统为了让数据读取速度与cpu对应,而在线程内分布一些存储空间–即缓存行。
这个缓存行也就解释了t1线程为何一直运行,因为缓存行仍保留着旧值。
如何确保写回主存的数据,让各线程知道缓存行数据 不对 呢?
---------缓存一致性协议,来实现这一功能。
缓存一致性协议的实现
-----每个线程对应一个处理器,而在处理器的总线中会存在“嗅探”检查,传播在总线,根据与自己线程缓存行数据对比是否失效。
volatile优化
试想如果缓存行的每行都有存储着不同数据,在多线程情况下,各个线程对不同共享变量进行操作,可能就存在当前线程刚修改一个值,其他线程缓存行失效,一会别的线程的修改,也导致了当前线程的缓存行的失效。这样一来效率就得不偿失了。
--------于是便通过追加字节来优化,通过占满一个缓存行保证一个缓存行有一个数据。
好啦,这就是小编对volatile的理解,如果有一些异议还望各位大佬点评!