前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >R大有时会颠覆你对Java的认知

R大有时会颠覆你对Java的认知

作者头像
程序员小强
发布2019-09-20 17:06:27
5730
发布2019-09-20 17:06:27
举报

关于volatile变量的内存可见性,我在JVM群中抛出了一个问题,然后我的一些认知就被颠覆了。

问题

请教一个问题,a,b,c三个变量,其中c是volatile的,a,b是普通变量, a = 1, b = 2, c = 3, c写入之后,a,b的值也会被刷入缓存吗,还是c写入之前所有在cpu缓存的数据都会被刷入内存,还是只刷入和c在同一个缓存行的数据?

一开始,我的认知是后者,只刷入同一个缓存行的数据。

R大问答

你们要按happens before来考虑这种问题,不要整天无谓想着擦车(cache),Java的修正过的内存模型其实基本点很简单,同一线程内的副作用按程序顺序发生,所以a、b、c的赋值如果是在同一线程内按这个顺序写的,实际执行就要按照这个顺序发生(至少表象上要按照这个顺序;在程序无法感知顺序差异时可以作弊)

这样就是a赋值happens before b赋值,b赋值happens before c赋值,而不同线程之间的操作则是没有happens before关系的,除非有volatile或者synchronized等带有跨线程happen before关系的操作。不同线程之间的非volatile、非synchronized操作直接要想有传递的happens before关系的话,中间就肯定得有能产生happens before关系的volatile或者synchronized操作。

什么寄存器啊、缓存啊啥的不必扯进来。

我的反应

哦~~~问号脸。。。

R大继续解释

JVM实现的时候是要把这些概念映射下去的(这里的概念应该就是happens before),但是当你在思考高层程序语义的时候却拿不合适的低层语义去解释就很别扭,映射下去的办法就是先有高层语义,然后看具体硬件上提供了哪些原语,然后再去实现。例如说在SPARC上它默认是TSO(total store order)的,在上面需要手工做的同步操作就很简单。

晓铭大大的总结

JIT的时候会去查操作数的属性,如果是volatile会在读写操作附近生成barrier的中间表示,最终barrier中间表示会变成什么指令,那要根据具体的机器,Memory consistency是一个spec,各种硬件系统包括cache都是实现的细节。

总结

总结起来,我这个问题问的不好,没水准,问题直接从jmm跳到了硬件具体实现,具体实现都不一样,中间还隔着一层硬件的memory model。

所以缓存到底怎么刷,不同的CPU、不同厂商、不同型号实现可能都不一样,一个人想了解所有似乎是个不可能的任务,也不实用,只需要搞清楚JMM层面的东西就OK,管它到底怎么刷。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-01-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 MoziInnovations 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题
  • R大问答
  • 我的反应
  • R大继续解释
  • 晓铭大大的总结
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档