- 当第二个操作是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中都必须具有原子性(即任意读操作必须要在单个读事务中执行) 。
作者:双子孤狼
原文链接:
推荐阅读
-
-
华大基因前三季度净利预计超26亿元 同比增长约900%
-
港股挖掘机|洛阳玻璃股份(01108)附属太阳能材料项目5月28日顺利投产
-
不含香精的国产护肤品 佰草百丽日本小分子透明质酸钠原液
-
最受大众“喜爱”的城市,不是我们熟悉的北京,反而是这座城市!
-
-
161的身高一般买f的内衣腰围52咋穿衣服!不想性感森女!其他的都可以!咋破穿!我还有一张娃娃脸?
-
新车|艳丽,兰博基尼Huracán EVO后驱版亮相广州车展
-
人走茶凉|华为HCIA/HCIP/HCIE数通Datacom系列,OSPF基础配置讲解
-
-
少年一梦|马斯克脑机接口刚出来,浙大传来好消息,我国在AI领域再攻下一城
-
河北一杂技学校4名学生在成都失联,其中两人已被找到
-
-
?人民日报客户端|印尼新冠肺炎新增确诊1752例 累计确诊84882例
-
减肥|要想减肥成功且不反弹,这五大“雷区”,你还敢踩吗?
-
-
ZAKER|新桥城管中队:拆!,公共停车场私设地锁
-
#公益#记忆中没看过她作品,但年年来金鸡百花刷存在感,逢“鸡”必到
-
【东南地区】自宋代以后,为何没有朝代定都于关中,如长安这些地方?
-