为了账号安全,请及时绑定邮箱和手机立即绑定

java 的内存模型(Java Memory Model)

标签:
Java

改变执行顺序

编译器、JVM 或者 CPU 共同努力通过改变执行顺序来最求程序的执行效率。
我们通常coding 时候,代码的执行是有一定顺序,这样保证我们可以完成一定逻辑,但是在 JVM 执行代码会根据需要,也就是最求性能来调整我们代码执行顺序。
但是这样调整顺序并不会影响程序执行的结果。

a = 3
b = 2
a = a + 1;

这是上面代码的 JVM 执行的情况,我们加载 a 然后为 a 进行赋值,然后将其保存到内存中,同样操作在下两条语句。

Load aSet to 3Store a

Load bSet to 2Store b

Load aSet to 4Store a

我们发现执行过程中 load a 被执行了两次,我们需要对此进行优化。具体优化如下

a = 3
a = a + 1

b = 2
Load aSet to 3set to 4Store a

Load bSet to 2Store b

这些具体优化工作是 JVM 中完成的。

可见性

多线程的中一致性的表现,又叫做并发


webp

007.JPG

我们看最上面一层 core 这里表示有 4 个 cpu,每一个 cpu 都有一个 registers(注册机),然后就是 L1 cache 一级缓存,虽然不大因为 cpu 直接从这里读取内存所以这里非常快。然后就是 L2 二级缓存这里就是两个 core 来共享的。到了 3L 缓存就是所有 core 共享的内存区域。离 cpu 越远的缓存会访问速度降低同时容量变大。

public class FieldVisibility{  int x = 0;  public void writerThread(){
    x = 1
  }  public void readerThread(){    int r2 = x;
  }
}

这里创建一个 FieldVisibility 类,初始化 x = 0,让后提供两个方法分别在不同的线程对 x 进行读写操作。


webp

008.JPG

然后创建两个 FieldVisibility 的实例分别调用读和写方法来读写 x。

webp

009.JPG

当我们一个实例调用 writerThread 方法来修改 x 的值为 1,x = 1 仅会保存在 local cache 本地缓存,而不会更新到 shared cache (共享缓存),所以当另一个实例调用 readerThread 来获取 x 的值,依旧得到是 0 而不是 1.

这就是字段可见性问题。

public class FieldVisibility{  volatile int x = 0;  public void writerThread(){
    x = 1
  }  public void readerThread(){    int r2 = x;
  }
}

webp

010.JPG

当我们用关键字 volatile 修饰字段 x 时,当 x 发生变化会更新共享缓存,这样就保证 x 的更改对其他方法可见性。


webp



作者:zidea
链接:https://www.jianshu.com/p/5fcd7b2e7835


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
205
获赞与收藏
1008

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消