volatile 关键字是一个神秘的关键字,也许在 J2EE 上的 JAVA 程序员会了解多一点,但在 Android 上的 JAVA 程序员大多不了解这个关键字。只要稍了解不当就好容易导致一些并发上的错误发生,例如好多人把 volatile 理解成变量的锁。(并不是)

volatile 的特性:
具备可见性
保证不同线程对被 volatile 修饰的变量的可见性。
有一被 volatile 修饰的变量 i,在一个线程中修改了此变量 i,对于其他线程来说 i 的修改是立即可见的。
如:
volatile int i = 0;// 语句 1 i++; // 语句 2
语句 2 执行完后,i 最新的值会立即被强制更新到主内存(共享内存),并通知其他缓存了 i 的线程,令其他线程的工作内存里的 i 失效,从而需重新到主内存读取最新的值。
具备有序性
被 volatile 修饰的变量,不会被优化排序。
解决的问题详见:Java 多线程并发编程 并发三大要素 的 三、有序性。
当编译器在给程序优化排序时,若遇到 volatile 变量的读操作或者写操作,则会保证在其前面的操作全部进行完成,且结果对后面的操作可见;并且保证在其后面的操作没有进行。
不具备原子性
volatile 不具备原子性,所以它是线程不安全的。
实验:
// 一个单例的实现
public class SingletonTest {
private static volatile SingletonTest mInstance = null;
private SingletonTest() {}
public static SingletonTest getInstance() {
if (mInstance == null) {
mInstance = new SingletonTest();
System.out.println(" 初始化完成 ");
}
return mInstance;
}
}
// 测试代码
public class Test {
public static void main(String[] var0) {
for(int i = 0; i < 20; i++){
ThreadTest test = new ThreadTest();
test.start();
}
}
static class ThreadTest extends Thread{
@Override
public void run() {
super.run();
SingletonTest.getInstance();
}
}
}
结果:
每次运行都输出多个 “初始化完成”。
volatile 的解释
下面这段话摘自《深入理解 Java 虚拟机》:
“观察加入 volatile 关键字和没有加入 volatile 关键字时所生成的汇编代码发现,加入 volatile 关键字时,会多出一个 lock 前缀指令”
被 volatile 修饰的变量进行读和写操作的时候,在相应的汇编程序中都会多一句内存屏障(Memory Barrier)。
而这个 lock 就是内存屏障。
内存屏障的作用:
1、在重新优化排序时保证其后面的指令不会被排到内存屏障的前面,前面的指令也不会排到内存屏障的后面。- 有序性
2、强制对写操作后的结果(立即)刷新到主内存。
3、刷新结果到主内存时,通知并令其他线程缓存内的值过期 / 失效。
2 和 3 合起来则是可见性。
说到这里,也许会有好多人困惑,既然可见性可以保证,既然可以做到修改某个变量的值后,会刷新到主内存,并令其他线程缓存失效,为什么不能保证原子性呢?这也是我之前走进的一个困区。
继续用 i++ 来分析一下,这里面包含的指令:
从主内存读取到缓存 // 指令 1
进行运算 // 指令 2
从缓存刷新到主内存 // 指令 3
内存屏障 // 指令 4
虽然指令 4(内存屏障)功能强大,但可惜 // 指令 1、2、3 都不是具备原子性,所以导致 volatile 不具备原子性,线程不安全,不能替代锁的作用。
使用场景
如一些简单的状态标记:
volatile boolean inited = false;
// 线程 1
init(); // 语句 1
inited = true; // 语句 2
// 线程 2
while(inited){
work(); // 语句 3
}
1、可确保语句 1 和语句 2 的执行顺序。
2、可确保执行语句 2 后,线程 2 可立即获取到最新的修改,从而执行语句 3。
# Java
# Volatile
# 关键字
# Java并发编程之常用的多线程实现方式分析
# Java多线程并发编程和锁原理解析
# 深入理解Java多线程与并发编程
# Java多线程并发编程(互斥锁Reentrant Lock)
# Java多线程之并发编程的核心AQS详解
# 不具备
# 见性
# 不安全
# 新到
# 是一个
# 汇编程序
# 有一
# 会有
# 一句
# 多个
# 则是
# 就好
# 但在
# 三大
# 说到
# 它是
# 不了解
# 这里面
# 多出
# 则会
相关文章:
高性价比服务器租赁——企业级配置与24小时运维服务
如何用PHP快速搭建高效网站?分步指南
如何在Windows虚拟主机上快速搭建网站?
建站主机选哪种环境更利于SEO优化?
网站视频制作书签怎么做,ie浏览器怎么将网站固定在书签工具栏?
企业微网站怎么做,公司网站和公众号有什么区别?
如何在Golang中引入测试模块_Golang测试包导入与使用实践
html制作网站的步骤有哪些,iapp如何添加网页?
外汇网站制作流程,如何在工商银行网站上做外汇买卖?
内网网站制作软件,内网的网站如何发布到外网?
佛山网站制作系统,佛山企业变更地址网上办理步骤?
建站主机服务器选购指南:轻量应用与VPS配置解析
家庭服务器如何搭建个人网站?
建站OpenVZ教程与优化策略:配置指南与性能提升
用v-html解决Vue.js渲染中html标签不被解析的问题
Android使用GridView实现日历的简单功能
建站主机如何选?性能与价格怎样平衡?
建站ABC备案流程中有哪些关键注意事项?
创业网站制作流程,创业网站可靠吗?
微信h5制作网站有哪些,免费微信H5页面制作工具?
魔方云NAT建站如何实现端口转发?
焦点电影公司作品,电影焦点结局是什么?
建站之星与建站宝盒如何选择最佳方案?
青岛网站设计制作公司,查询青岛招聘信息的网站有哪些?
教学网站制作软件,学习*后期制作的网站有哪些?
如何用已有域名快速搭建网站?
制作网页的网站有哪些,电脑上怎么做网页?
如何高效利用亚马逊云主机搭建企业网站?
建站主机选虚拟主机还是云服务器更好?
详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)
齐河建站公司:营销型网站建设与SEO优化双核驱动策略
大学网站设计制作软件有哪些,如何将网站制作成自己app?
建站之星代理平台如何选择最佳方案?
javascript基本数据类型及类型检测常用方法小结
建站之星伪静态规则如何正确配置?
武汉网站如何制作,黄黄高铁武穴北站途经哪些村庄?
自助网站制作软件,个人如何自助建网站?
制作门户网站的参考文献在哪,小说网站怎么建立?
建站之星安装失败:服务器环境不兼容?
西安大型网站制作公司,西安招聘网站最好的是哪个?
义乌企业网站制作公司,请问义乌比较好的批发小商品的网站是什么?
网站视频怎么制作,哪个网站可以免费收看好莱坞经典大片?
教学论文网站制作软件有哪些,写论文用什么软件
?
建站之星3.0如何解决常见操作问题?
微网站制作教程,我微信里的网站怎么才能复制到浏览器里?
网站设计制作企业有哪些,抖音官网主页怎么设置?
免费公司网站制作软件,如何申请免费主页空间做自己的网站?
无锡营销型网站制作公司,无锡网选车牌流程?
建站10G流量真的够用吗?如何应对访问高峰?
西安制作网站公司有哪些,西安货运司机用的最多的app或者网站是什么?
*请认真填写需求信息,我们会在24小时内与您取得联系。