-
概述
大家应该都听说过volatile这个关键字,我想很多人应该都不知道怎么用,现在我给大家讲讲我的理解,如果有什么不对的,希望大家可以指正,顺便也让我学习学习。在此非常感谢让我学习这些知识点的大佬们,也正是他们无私的奉献,才会让我有所收获。
首先,要想理解volatile是干什么的,就必须知道java的内存模式是什么,可以看看这位大佬的博客: -
配置环境
JIT或HotSpot编译器在server模式和client模式编译不同,server模式为了使线程运行更快,如果其中一个线程更改了变量boolean flag 的值,那么另外一个线程会看不到,因为另外一个线程为了使得运行更快所以从寄存器或者本地cache中取值,而不是从内存中取值,那么使用volatile后,就告诉不论是什么线程,被volatile修饰的变量都要从内存中取值。《内存栅栏》 -
测试代码
public class HelloWorld { boolean flag = true; Executor executor = Executors.newFixedThreadPool(4); public static void main(String[] args) { new HelloWorld().run(); } void run(){ executor.execute(new T1()); executor.execute(new T2()); } class T1 implements Runnable{ public void run() { while(flag){ int i = 0 ; System.out.println(i++); } } } class T2 implements Runnable{ public void run(){ while(flag){ try { Thread.sleep(1000); flag = false ; } catch (InterruptedException e) { e.printStackTrace(); } } } } }
-
总结
⑴java 在client模式下,多线程读取变量时,都会直接从主内存中去读取,不会保存在工作内存(缓存)中,所有加不加volatile效果是一样的,而server模式下,是对java虚拟机做了优化的,直接存缓存中读取,当执行完当下的方法,才会释放缓存。
⑵当在线程中存在同步块时,也会强制去主内存重新获取主内存的值,所以synchronize和lock也是满足共享变量可见性的。
请勿使用eclipse做测试,eclipse模式使用的client模式