
1.为阅读体验,本站无任何广告,也无任何盈利方法,站长一直在用爱发电,现濒临倒闭,希望有能力的同学能帮忙分担服务器成本
2.捐助10元及以上同学,可添加站长微信lurenzhang888,备注捐助,网站倒闭后可联系站长领取本站pdf内容
3.若网站能存活下来,后续将会持续更新内容
前面提到重排序可以提高代码的执行效率,但在多线程程序中可以导致程序的运行结果不正确,那
volatile
是如何解决这一问题的呢?
为了实现volatile
的内存语义,编译器在生成字节码时会通过插入内存屏障来禁止指令重排序。
内存屏障:内存屏障是一种CPU指令,它的作用是对该指令前和指令后的一些操作产生一定的约束,保证一些操作按顺序执行。
Java虚拟机插入内存屏障的策略
Java内存模型把内存屏障分为4类,如下表所示:
屏障类型 | 指令示例 | 说明 |
---|---|---|
LoadLoad Barriers | Load1;LoadLoad;Load2 | 保证Load1数据的读取先于Load2及后续所有读取指令的执行 |
StoreStore Barriers | Store1;StoreStore;Store2 | 保证Store1数据刷新到主内存先于Store2及后续所有存储指令 |
LoadStore Barriers | Load1;LoadStore;Store2 | 保证Load1数据的读取先于Store2及后续的所有存储指令刷新到主内存 |
StoreLoad Barriers | Store1;StoreLoad;Load2 | 保证Store1数据刷新到主内存先于Load2及后续所有读取指令的执行 |
注:StoreLoad Barriers同时具备其他三个屏障的作用,它会使得该屏障之前的所有内存访问指令完成之后,才会执行该屏障之后的内存访问命令。
Java内存模型对编译器指定的volatile
重排序规则为:
- 当第一个操作是
volatile
读时,无论第二个操作是什么都不能进行重排序。 - 当第二个操作是
volatile
写时,无论第一个操作是什么都不能进行重排序。 - 当第一个操作是
volatile
写,第二个操作为volatile
读时,不能进行重排序。
根据volatile
重排序规则,Java内存模型采取的是保守的屏障插入策略,volatile
写是在前面和后面分别插入内存屏障,volatile
读是在后面插入两个内存屏障,具体如下:
volatile
读:在每个volatile
读后面分别插入LoadLoad屏障及LoadStore屏障(根据volatile
重排序规则第一条),如下图所示

LoadLoad屏障的作用:禁止上面的所有普通读操作和上面的volatile
读操作进行重排序。
LoadStore屏障的作用:禁止下面的普通写和上面的volatile
读进行重排序。
volatile
写:在每个volatile
写前面插入一个StoreStore屏障(为满足volatile
重排序规则第二条),在每个volatile
写后面插入一个StoreLoad屏障(为满足volatile
重排序规则第三条),如下图所示

StoreStore屏障的作用:禁止上面的普通写和下面的volatile
写重排序
StoreLoad屏障的作用:防止上面的volatile
写与下面可能出现的volatile
读/写重排序。
本站链接:https://www.mianshi.online,如需勘误或投稿,请联系微信:lurenzhang888
点击面试手册,获取本站面试手册PDF完整版