如何验证volatile保证数据的可见性和有序性?
第一点:首先判断你的java环境中jvm是client模式还是server模式
Java HotSpot Client VM:为在客户端环境中减少启动时间而优化;比较适合桌面程序,它会做一些例如像快速初始化,懒加载这一类的事件来适应桌面程序的特点。
Java HotSpot Server VM:为在服务器环境中最大化程序执行速度而设计; 适合做服务器程序,一些针对服务器特点的事情,比如预加载,尤其在一些并发的处理上,是会做更多的优化。
补充知识点:
如果是64位的jdk 1.8 amd64,只能运行在Server模式下。而32位的jdk 1.8 i386,默认是运行在client模式下,可以通过修改jdk/jre/lib/i386/jvm.cfg文件里面的设置来指定默认的启动模式。默认32位jdk 1.8 i386为:
-client IF_SERVER_CLASS -server
-server KNOWN
-minimal KNOWN
将第一行注释,之后有:
#-client IF_SERVER_CLASS -server
-server KNOWN
-minimal KNOWN
第二点:根据上图确定现在我的是server模式执行以下的代码
package rs.thread.day0504;
/**
* @auther rs
* @date 2019/5/4 13:25
* @email 529811807@qq.com
* @weixinhao javawjs
*
* 验证 >>>> volatile也能保证数据的可见性和有序性???
*/
public class Test02_volatile {
private static boolean ready;
private static int number;
private static class ReaderThread extends Thread{
@Override
public void run() {
while(!ready);
System.out.println(number);
}
}
public static void main(String[]args) throws InterruptedException {
new ReaderThread().start();
Thread.sleep(1000);
number = 42;
ready = true;
Thread.sleep(10000);
}
}
由于是server模式下,系统已经优化的结果,ReaderThread线程无法看到主线程中的修改,导致ReaderThread永远无法退出,就是上面那个while永远不会成立,这显然不是我们想看到的结果,这个问题就是一个典型的可见性问题
第三点::我们切换jvm到client模式后由于jit没有做足够的优化,在主线程修改ready变量的状态后,ReaderThread可以发现改动,退出程序
结论::和原子性问题一样,我们只要简单地使用volatile来申明ready变量,告诉java虚拟机,这个变量可能会在不同的线程中修改,这样,就可以顺利解决这个问题了
欢迎转载,转载请注明出处!
github: rs1314
欢迎关注共公众号微信 : java微技术
分享我的学习之路和各种java技术,教程资料