volatile在java server模式和client模式下的不同(主内存和工作内存)
来源:互联网 发布:jdk1.8 for linux下载 编辑:程序博客网 时间:2024/06/06 21:39
因为要做一个java多线程的培训,而自己对多线程的理解也是一知半解。
尤其困惑的地方是对volatile关键字的理解。
好了,现在步入正题。
volalte的关键字是在多线程共享数据时,共享数据不会备份到各线程的工作内存中,而是直接从主内存中获取最新值,即是线程可见性。
以下是对volatile关键字的测试代码
public class VolatileTest {
public volatile static boolean asleep = true;
public static void main(String[] args) throws InterruptedException {
new Thread(new Runnable() { //称为线程1吧
@Override
public void run() {
while(asleep){
}
}
}).start();
Thread.sleep(1*1000);
asleep=false;
}
}
运行结果:
①有volatile关键字时,当主线程把asleep改成false时,线程1停止运行,符合预期结果
②将volatile去掉时,运行结果依然同上。
我纳闷了,为什么。如果是这样的情况,volatile关键字完全没有作用。
后来同事提醒我,将运行参数改成服务器模式,即 -server模式 (我的eclipse里默认执行是client模式)
重复上面步骤
①有volatile关键字时,当主线程把asleep改成false时,线程1停止运行,符合预期结果
②将volatile关键字去掉时,程序陷入死循环,线程1感受不到asleep的变化,埋头苦干。
在网上查资料,以下
JIT或HotSpot编译器在server模式和client模式编译不同,server模式为了使线程运行更快,如果其中一个线程更改了变量boolean flag 的值,那么另外一个线程会看不到,因为另外一个线程为了使得运行更快所以从寄存器或者本地cache中取值,而不是从内存中取值,那么使用volatile后,就告诉不论是什么线程,被volatile修饰的变量都要从内存中取值。《内存栅栏》
说明server对java代码做了更多的优化,而client却没有。
笔者不甘心,继续做实验
在-server模式下,修改以上的代码,
public class VolatileTest {
public volatile static boolean asleep = true;
public static void main(String[] args) throws InterruptedException {
new Thread(new Runnable() { //称为线程1吧
@Override
public void run() {
while(asleep){
System.out.println("我不信啦!!");
}
}
}).start();
Thread.sleep(1*1000);
asleep=false;
}
}
执行代码,这次笔者笑啦
①有volatile关键字时,当主线程把asleep改成false时,线程1停止运行,符合预期结果
②将volatile关键字去掉时,结果如上。
这是为什么呢???
为什么这次不加volatile,线程1又能感受asleep的变化呢????
问题就出在System.out.println("我不信啦!!");这段代码上
因为System.out.println中含有同步块,一执行该方法,变量将从主存中重新读取。
System.out.println如下:
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
为了验证这个验证,笔者继续做实验
在-server模式下,修改以上的代码,
public class VolatileTest {
public static boolean asleep = true;
public static void main(String[] args) throws InterruptedException {
new Thread(new Runnable() {
public void run() {
while (asleep) {
//笔者把System.out.printlnd换成了下面
int a = 1, b = 2;
int c = a + b;
}
}
}).start();
Thread.sleep(1 * 1000);
asleep = false;
}
}
执行代码,得出如下
①有volatile关键字时,当主线程把asleep改成false时,线程1停止运行,符合预期结果
②将volatile关键字去掉时,程序陷入死循环,线程1感受不到asleep的变化,埋头苦干。
验证我的猜测!!!
结论:
⑴java 在client模式下,多线程读取变量时,都会直接从主内存中去读取,不会保存在工作内存中,所有加不加volatile效果一下,而server模式下,则对代码做了优化。
⑵当在线程中存在同步快时,会强制去主内存重新获取主内存的值。
以上结果全部运行在jdk1.6的环境下
下班啦!!!~~~第一次发博客,心情这个忐忑啊!!
内容有些凌乱,回去在整理 O(∩_∩)O哈哈~
- volatile在java server模式和client模式下的不同(主内存和工作内存)
- 浅谈Java虚拟机的工作模式Client和Server。
- 浅谈Java虚拟机的工作模式Client和Server。
- 内存溢出和内存泄露、并行和并发、Minor GC和Full GC、Client模式和Server模式的区别
- 8.《深入理解Java虚拟机》内存溢出和内存泄露、并行和并发、Minor GC和Full GC、Client模式和Server模式的区别
- Java虚拟机6:内存溢出和内存泄露、并行和并发、Minor GC和Full GC、Client模式和Server模式的区别
- JVM的server模式和client模式
- JVM的Server模式和Client模式
- java并发编程实践学习(三)JVM的server模式和client模式
- volatile在debug和release模式下的意义
- hotspot 虚拟机的server和client模式
- JVM -server和-client模式
- JVM client模式和Server模式的区别
- JVM client模式和Server模式的区别
- JVM client模式和Server模式的区别
- JVM client模式和Server模式的区别
- JVM client模式和Server模式的区别
- JVM client模式和Server模式的区别
- 屏幕空间环境遮挡(SSAO)特效
- Intel Thread Building Blocks (TBB) 的介绍
- 黑马程序员--jdk1.5的新特性:泛型(重点,集合中的泛型一定要会)
- 自定义类似php的js数组的in_array函数
- SqlServer转换为Mysql的一款工具推荐(mss2sql)
- volatile在java server模式和client模式下的不同(主内存和工作内存)
- 第一次调用微信官方的Demo应该怎样才能运行成功
- android中图片的三级cache策略(内存、文件、网络)之三:文件缓存策略
- websphere 与 tomcat 关于java获取 jndi区别
- IOS百度地图开发系列-百度地图不能正常显示
- Unix/Linux进程间通信——FIFO
- 辞职的时候,如果老板挽留你,你会怎么办呢?
- SunShafts 阳光射线特效(也称之天空光,上帝射线)
- php相对目录比较