概述

Java语言中关键字 volatile 被称作轻量级的 synchronized,与synchronized相比,volatile编码相对简单且运行的时的开销较少,但能够正确合理的应用好 volatile 并不是那么的容易,因为它比使用锁更容易出错,接下来本文主要介绍 volatile 的使用准则,以及使用过程中需注意的地方。
为何使用volatile?
(1)简易性:在某些需要同步的场景下使用volatile变量要比使用锁更加简单
(2)性能:在某些情况下使用volatile同步机制的性能要优于锁
(3)volatile操作不会像锁一样容易造成阻塞
volatile特性
(1)volatile 变量具有 synchronized 的可见性特性,及如果一个字段被声明为volatile,java线程内存模型确保所有的线程看到这个变量的值是一致的
(2)禁止进行指令重排序
(3)不保证原子性
注:
① 重排序:重排序通常是编译器或运行时环境为了优化程序性能而采取的对指令进行重新排序执行的一种手段
② 原子性:不可中断的一个或一系列操作
③ 可见性:锁提供了两种主要特性:互斥和可见性,互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据。可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的。
volatile的实现原理
如果对声明了volatile的变量进行写操作,JVM就会向处理器发送一条Lock前缀的指令,该Lock指令会使这个变量所在缓存行的数据回写到系统内存,根据缓存一致性协议,每个处理器都会通过嗅探在总线上传输的数据来检查自己缓存的值是否已过期,当处理器发现自己的缓存行对应的地址被修改,就会将当前处理器的缓存行设置成无效状态,在下次访问相同内存地址时,强制执行缓存行填充。
正确使用volatile的场景
volatile 主要用来解决多线程环境中内存不可见问题。对于一写多读,是可以解决变量同步问题,但是如果多写,就无法解决线程安全问题。如:
1、不适合使用volatile的场景(非原子性操作)
(1)反例
private static volatile int nextSerialNum = 0;
public static long generateSerialNum() {
return nextSerialNum++;
}
这个方法的目的是要确保每次调用都返回不同的自增值,然而结果并不理想,问题在于增量操作符(++)不是原子操作,实际上它是一个由读取-修改-写入操作序列组成的组合操作,如果第二个线程在第一个线程读取旧值和写回新值期间读取这个域,第二个线程与第一个线程就会读取到同一个值。
(2)正例
其实面对上面的反例场景可以使用JDK1.5 java.util.concurrent.atomic中提供的原子包装类型来保证原子性操作
private static AtomicInteger nextSerialNum = new AtomicInteger(0);
public static long generateSerialNum() {
return nextSerialNum.getAndIncrement();
}
2、适合使用volatile的场景
在日常工作当中volatile大多被在状态标志的场景当中,如:
要通过一个线程来终止另外一个线程的场景
(1)反例
private static boolean stopThread;
public static void main(String[] args) throws InterruptedException {
Thread th = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while (!stopThread) {
i++;
}
}
});
th.start();
TimeUnit.SECONDS.sleep(2);
stopThread = true;
}
运行后发现该程序根本无法终止循环,原因是,java语言规范并不保证一个线程写入的值对另外一个线程是可见的,所以即使主线程main函数修改了共享变量stopThread状态,但是对th线程并不可见,最终导致循环无法终止。
(2)正例
private static volatile boolean stopThread;
public static void main(String[] args) throws InterruptedException {
Thread th = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while (!stopThread) {
i++;
}
}
});
th.start();
TimeUnit.SECONDS.sleep(2);
stopThread = true;
}
通过使用关键字volatile修饰共享变量stopThread,根据volatile的可见性原则可以保证主线程main函数修改了共享变量stopThread状态后对线程th来说是立即可见的,所以在两秒内线程th将停止循环。
总结
本文通过对volatile的特性介绍,以及volatile的实现原理,最后结合volatile的特性举例说明它在使用过程中应该注意的使用规则,好了,希望本文对您有所帮助!
# java
# volatile关键字
# Java开发中的volatile你必须要了解一下
# 详解Java面试官最爱问的volatile关键字
# 深入分析java并发编程中volatile的实现原理
# Java中Volatile关键字详解及代码示例
# Java线程之线程同步synchronized和volatile详解
# java中volatile和synchronized的区别与联系
# java中volatile不能保证线程安全(实例讲解)
# java volatile关键字使用方法及注意事项
# Java中volatile关键字实现原理
# Java关键字volatile和synchronized作用和区别
# Java多线程并发编程 Volatile关键字
# java 高并发中volatile的实现原理
# java 中volatile和lock原理分析
# Java中Volatile的作用实例解析
# 见性
# 第一个
# 第二个
# 另外一个
# 反例
# 过程中
# 自己的
# 就会
# 好了
# 互斥
# 两种
# 它是
# 在某些
# 发现该
# 线上
# 只有一个
# 要比
# 可以使用
# 会使
# 写到
相关文章:
建站之星后台密码遗忘如何找回?
深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?
网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?
如何用景安虚拟主机手机版绑定域名建站?
在线ppt制作网站有哪些,请推荐几个好的课件下载的网站?
建站之星导航菜单设置与功能模块配置全攻略
如何自定义建站之星网站的导航菜单样式?
如何在Windows服务器上快速搭建网站?
高性价比服务器租赁——企业级配置与24小时运维服务
如何基于云服务器快速搭建网站及云盘系统?
如何高效利用200m空间完成建站?
韩国网站服务器搭建指南:VPS选购、域名解析与DNS配置推荐
网站制作需要会哪些技术,建立一个网站要花费多少?
建站之星后台密码如何安全设置与找回?
css网站制作参考文献有哪些,易聊怎么注册?
广州网站制作公司哪家好一点,广州欧莱雅百库网络科技有限公司官网?
实现虚拟支付需哪些建站技术支撑?
如何在万网主机上快速搭建网站?
音乐网站服务器如何优化API响应速度?
宝塔建站后网页无法访问如何解决?
企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?
如何在搬瓦工VPS快速搭建网站?
宝塔新建站点报错如何解决?
专业网站建设制作报价,网页设计制作要考什么证?
昆明高端网站制作公司,昆明公租房申请网上登录入口?
如何有效防御Web建站篡改攻击?
长沙企业网站制作哪家好,长沙水业集团官方网站?
如何通过智能用户系统一键生成高效建站方案?
如何在服务器上配置二级域名建站?
建站之星各版本价格是多少?
c# 在高并发下使用反射发射(Reflection.Emit)的性能
建站主机选哪种环境更利于SEO优化?
如何设置并定期更换建站之星安全管理员密码?
海南网站制作公司有哪些,海口网是哪家的?
孙琪峥织梦建站教程如何优化数据库安全?
宝塔面板创建网站无法访问?如何快速排查修复?
建站之星在线客服如何快速接入解答?
如何通过可视化优化提升建站效果?
,sp开头的版面叫什么?
建站之星免费模板:自助建站系统与智能响应式一键生成
如何在云指建站中生成FTP站点?
宝华建站服务条款解析:五站合一功能与SEO优化设置指南
成都网站制作公司哪家好,四川省职工服务网是做什么用?
已有域名建站全流程解析:网站搭建步骤与建站工具选择
制作证书网站有哪些,全国城建培训中心证书查询官网?
建站之星安装提示数据库无法连接如何解决?
儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?
建站之星多图banner生成与模板自定义指南
C++中的Pimpl idiom是什么,有什么好处?(隐藏实现)
学校建站服务器如何选型才能满足性能需求?
*请认真填写需求信息,我们会在24小时内与您取得联系。