JVM学习(九)volatile应用

2023-05-30,,

一、初认volatile

  首先学习volatile关键字时,我们先简单的了解一下它能干啥:

  工作内存与主内存同步延迟现象导致的可见性问题:

可通过synchronized或volatile关键字解决,他们都可以使一个线程修改后的变量立即对其它线程可见

  对于指令重排导致的可见性问题和有序性问题:

可以使用volatile关键字解决,因为volatile关键字的另一个作用就是禁止重排序优化

二、内存屏障

  我们知道了volatile关键字其中一个功能可以禁止指令重排序,那么它是怎么实现的呢,这里引出一个内存屏障的概念:

  概念:内存屏障,也称内存栅栏,内存栅障,屏障指令等, 是一类同步屏障指令,是CPU或编译器在对内存随机访问的操作中的一个同步点,使得此点之前的所有读写操作都执行后才可以开始执行此点之后的操作

  作用:

保证特定操作的顺序
保证某些变量的内存可见性(利用该特性实现volatile的内存可见性)

种类:

三、volatile关键字在程序运行中的表现

四、volatile和synchronized的区别

volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的。
volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性。
volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
volatile标记的变量不会被编译器优化【不会被重排序】;synchronized标记的变量可以被编译器优化【可以被重排序】。

五、volatile为啥不能保证原子性

  Q:问题来了,既然它可以保证修改的值立即能更新到主存,其他线程也会捕捉到被修改后的值,那么为什么不能保证原子性呢?

  A:首先需要了解的是,Java中只有对基本类型变量的赋值和读取是原子操作,如i = 1的赋值操作,但是像j = i或者i++这样的操作都不是原子操作,因为他们都进行了多次原子操作,比如先读取i的值,再将i的值赋值给j,两个原子操作加起来就不是原子操作了。 所以,如果一个变量被volatile修饰了,那么肯定可以保证每次读取这个变量值的时候得到的值是最新的,但是一旦需要对变量进行自增这样的非原子操作,就不会保证这个变量的原子性了。

参考文章:

Volatile禁止指令重排序(三)
volatile如何保证有序性?内存屏障都不知道怎么拿offer呀
volatile和synchronized的区别
volatile为什么不能保证原子性

JVM学习(九)volatile应用的相关教程结束。

《JVM学习(九)volatile应用.doc》

下载本文的Word格式文档,以方便收藏与打印。