- 当第二个操作是volatile写时 , 不管第一个操作是什么 , 都不能重排序 。 这个规则确保volatile写之前的操作不会被编译器重排序到volatile写之后 。
- 当第一个操作是volatile读时 , 不管第二个操作是什么 , 都不能重排序 。 这个规则确保volatile读之后的操作不会被编译器重排序到volatile读之前 。
- 当第一个操作是volatile写 , 第二个操作是volatile读时 , 不能重排序 。
为了实现volatile的内存语义 , 编译器在生成字节码时 , 会在指令序列中插入内存屏障来禁止特定类型的处理器重排序 。 对于编译器来说 , 发现一个最优布置来最小化插入屏障的总数几乎不可能 。 为此 , JMM采取保守策略 。 下面是基于保守策略的JMM内存屏障插入策略:
- 在每个volatile写操作的前面插入一个StoreStore屏障 。
- 在每个volatile写操作的后面插入一个StoreLoad屏障 。
- 在每个volatile读操作的后面插入一个LoadLoad屏障 。
- 在每个volatile读操作的后面插入一个LoadStore屏障 。
最后需要特别提一下原子性 , Java语言规范鼓励但不强求JVM对64位的long型变量和double型变量的写操作具有原子性 。 当JVM在这种处理器上运行时 , 可能会把一个64位long/double型变量的写操作拆分为两个32位的写操作来执行 , 这两个32位的写操作可能会被分配到不同的总线事务中执行 , 此时对这个64位变量的写操作将不具有原子性 。 锁的语义决定了临界区代码的执行具有原子性 。 但是因为一个volatile变量的读 , 总是能看到(任意线程)对这个volatile变量最后的写入 , 所以即使是64位的long型和double型变量 , 只要它是volatile变量 , 对该变量的读/写就具有原子性 。 但是多个volatile操作或类似于i++这种复合操作 , 这些操作整体上不具有原子性 。 针对于复合操作如i++这种 , 如果要保证原子性 , 需要通过synchronized关键字或者加其他锁来处理 。 注意:在JSR-133之前的旧内存模型中 , 一个64位long/double型变量的读/写操作可以被拆分为两个32位的读/写操作来执行 。 从JSR-133内存模型开始(即从JDK5开始) , 仅仅只允许把一个64位long/double型变量的写操作拆分为两个32位的写操作来执行 , 任意的读操作在JSR-133中都必须具有原子性(即任意读操作必须要在单个读事务中执行) 。
作者:双子孤狼
原文链接:
推荐阅读
-
花卉:养花经常掉叶子?可能是浇水出问题,赶紧改了,别忽视!
-
-
-
爱豆App|真-电竞小说男主伯贤:“我终于可以吃鸡了!”
-
-
上海市知识产权局网站|黄浦区多措并举积极推进知识产权领域双随机抽查工作
-
新作|苍天白鹤携新作强势来袭,将《星峰传说》挤至榜二,9.9分夺榜一
-
-
-
王者荣耀|S20赛季即将结束,夏洛特似女装亚瑟,钟馗也要出恐吓流玩法!
-
#第一篮球视角#书豪隔空送祝福:纽约,我从心底里爱着你,尼克斯重播林疯狂时刻
-
青年|天龙老玩家为了奔现有多拼因一件棉衣造成的误会,结局皆大欢喜
-
央视累计71157例,加拿大新增新冠肺炎确诊病例1176例
-
『TOPWOMEN时髦笔记』次次出手都精彩绝伦,纪梵希“女魔头”正式卸任!三年高定系列
-
江西都市现场|妻子抱怨丈夫总在晚上出去,民警一查,发现事情不简单
-
澎湃新闻|安倍晋三连续执政时间刷新纪录,政治遗产依然模糊?
-
-
《庆余年2》播出有消息:郭麒麟壮到不敢认,叶灵儿换人成唯一败笔
-
电池|三星Galaxy F41发布,6400万三摄+6000MAh,起售价1575元
-
直播吧|内维尔:蒂亚戈英语好在那里没用,利物浦当地口音太重