Java volatile 从入门到精通

 欢迎大家关注我的公众号,会不定期更新一些开发与测试的一些技术文章。

 

上篇我们一起学习了synchronized的各种骚操作,见synchronized的各种骚操作骚要点-对象锁、类锁、this锁、非this锁等 本篇来来看下和synchronized齐名的volatile,不管你听到的是同步的一种弱形式也好,还是听到的最轻量的同步机制,都是java研究者给予volatile关键字的美誉。

本文要点:

1、synchronized和volatile的特性差异

2、使用volatile需要满足的条件

3、volatile特性在虚拟机层面的实现

4、volatile示例代码

1、synchronized和volatile的特性差异

1.1、synchronized保证可见性和原子性,而volatile仅保证可见性。原子性大家应该都知道了,关于可见性,是指当一个线程修改了被volatile修饰的变量后,新值对于其他线程来说,是可以立即得知的。原理见下文;

1.2、synchronized可能会造成线程的阻塞,而volatile不会阻塞;

1.3、当共享数据的改变依赖于该数据之前的值时,synchronized可以保证线程

安全性,而volatile不行。volatile仅适用于共享变量作为独立的状态开关时的线程安全性,如标识完成、中断等的标记使用。(根本原因是volatile仅保证可见性);

1.4、synchronized修饰方法或代码块,volatile修饰变量,且被volatile修饰的变量不会参加重排序;

在虚拟机的happens-before规则中,有一条是关于volatile的,如下:

volatile变量规则( Volatile Variable Rule) : 对一个volatile变量的写操作先行发生于后面对这个变量的读操作, 这里的“后面”同样是指时间上的先后顺序。 

而关于happens-before规则,也就是先行规则,是指java内存模型中定义的两项操作之间的偏序关系,如果操作A在B之前发生,那么操作A产生的影响应该能被操作B观察到,影响包括很多,比如改变了共享变量的值,发送了消息、进行了方法调用以及返回了值等。对happens-before规则感兴趣的话,可以自行了解下java内存模型的这块。

2、使用volatile需要满足的条件

2.1、该变量的修改不依赖变量的当前值或能确保只有单一线程能修改该变量值;

2.2、变量不需要和其他变量共同参与不变约束;

注:关于不变约束,简单的说就是1+2=3,不管在顺序执行程序中,还在多线程执行程序中,1+2都应该等于3,而不应该等于其他。

2.3、访问变量时,没有其他的原因需要加锁;

3、volatile特性在虚拟机层面的实现

虚拟会保障以一种可预见的方式告知其他线程被volatile修饰的变量的更新,即,如果被volatile修饰的变量被一个线程A更新,那么线程A工作内存中更新后的值会直接刷到主内存中,当其他线程需要用到该变量时,发现该变量是被volatile修饰,即使其他线程的工作内存中有该变量的副本值,也会直接从主内存中加载该变量的值进行使用。作为对比,我们看下普通变量在各个线程中的使用方式,普通变量在多线程环境下,也会在各个线程的工作内存中保存着一份线程的副本,但各个线程在使用该普通变量时,仅会关注各自工作内存中的副本值,而不会主动进行数据的通讯和同步。

4、volatile示例代码

4.1、是否使用volatile修饰的共享变量

如下图所示:

上面两个图代码,在服务端模式下运行时,会在打印出"下面终止运行"后也一直打印"运行中..."。

注:读者在自己电脑下运行时可能会在打印出"下面终止运行"便真的终止了,出现这种情况的原因是自己的虚拟机并非在服务器模式下运行的。

当如下图中所示,加了红线上放的volatile后,则会正常的终止打印了。

4.1、使用volatile修饰的共享的变量自增

如下面两个图所示:

打印结果如下:可见并不能正常的进行自增操作,按我们的预期count值应该是100*100,但实际结果却并非如我们预期。

本篇完。

 欢迎大家关注我的公众号,会不定期更新一些开发与测试的一些技术文章。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值