volatile关键字解析~高级java必问

昨天我介绍了原子性、可见性、有序性的概念,那么今天就来见识下这些概念的主角-volatile关键字。

volatile基本介绍

volatile可以看成是synchronized的一种轻量级的实现,但volatile并不能完全代替synchronized,volatile有synchronized可见性的特性,但没有synchronized原子性的特性。可见性即用volatile关键字修饰的成员变量表明该变量不存在工作线程的副本,线程每次直接都从主内存中读取,每次读取的都是最新的值,这也就保证了变量对其他线程的可见性。另外,使用volatile还能确保变量不能被重排序,保证了有序性。

volatile只用修饰一个成员变量,如:private volatile balance;

volatile比synchronized编程更容易且开销更小,但具有一点的使用局限性,使用要相当小心,不能当锁使用。volatile不会像synchronized一样阻塞程序,如果是读操作远多于写操作的情况可以建议使用volatile,它会有更好的性能。

volatile使用场景

如果正确使用volatile的话,必须依赖下以下种条件:

1、对变量的写操作不依赖当前变量的值;

2、该变量没有包含在其他变量的不变式中。

第1个条件就说明了volatile不是原子性的操作,不能使用n++类似的计数器,它不是线程安全的。

1、状态的改变

有些场景肯定会有状态的改变,完成一个主线程的停止等。首先我们开启了一个无限循环的主线程,判断变量isStop变量是否为true,如果true的话就退出程序,否则就一直循环,所以这个isStop的值是别的线程改变的。

上面这段程序如果不加volatile的话会一直卡在循环,此时的线程拿到的值永远为false,加了volatile3秒后就输出stop,所以这段程序很好的解释了可见性的特点。

2、读多写少的情况

假设这样一种场景,有N个线程在读取变量的值,只有一个线程写变量的值,这时候就能保证读线程的可见性,又能保证写线程的线程安全问题。

像n++不是原子类的操作,其实可以通过synchronized对写方法锁住,再用volatile修饰变量,这样就保证了读线程对变量的可见性,又保证了变量的原子性。

如果n不加volatile,程序将一直循环,不能输出stop,也就是此时的线程拿到的值永远为0。当然不加volatile,对获取n的方法进行synchronized修饰也是能及时获取最新值的,但是性能会远低于volatile。

原文发布于微信公众号 - Java技术栈(javastack)

原文发表时间:2017-06-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏用户2442861的专栏

《Java虚拟机原理图解》 1.1、class文件基本组织结构

http://blog.csdn.net/luanlouis/article/details/39892027

912
来自专栏程序员同行者

Python基础之函数等等

需要删除:? 需要新建:? 需要更新:?  注意:无需考虑内部元素是否改变,只要原来存在,新汇报也存在,就是需要更新

1504
来自专栏向治洪

java基础Haep(堆)和Stack(栈)区别

简单的可以理解为: heap:是由malloc之类函数分配的空间所在地。地址是由低向高增长的。  stack:是自动分配变量,以及函数调用的时候所使用的一些空...

2107
来自专栏iOSDevLog

How do you compare two version Strings in Java?

https://stackoverflow.com/questions/198431/how-do-you-compare-two-version-string...

1094
来自专栏纯洁的微笑

jvm系列(一):java类的加载机制

1、什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个 java.lang.Cl...

3856
来自专栏JavaEdge

JVM内存模型1 程序计数器2. Java虚拟机栈(JVM Stack)3. 本地方法栈(Native Method Stack)4 Java堆(Java Heap)5 方法区6 直接内存(Direc

4349
来自专栏移动端开发

iOS 开发之Block

iOS 开发之Block 一:什么是Block。Block的作用      UI开发和网络常见功能的实现回调,按钮事件的处理方法是回调方法。     1.   ...

20310
来自专栏Python中文社区

Python3.7 contextvars 初探

Python 3.7 于2018年6月27日发布,本篇文章将对其中新增模块contextvars 做初步介绍,为读者勾勒一个大概轮廓。

1635
来自专栏大数据架构师专家

Python操作Redis的最佳实践

4584
来自专栏黑泽君的专栏

动态代理详解

动态代理它可以直接给某一个目标对象生成一个代理对象,而不需要代理类存在。     动态代理与代理模式原理是一样的,只是它没有具体的代理类,直接通过反射生成了一...

872

扫码关注云+社区

领取腾讯云代金券