乐趣区

关于java:volatile-底层是如何实现的

在 Java 中,volatile 是一种关键字,用于润饰变量。 应用 volatile 关键字润饰的变量具备可见性和有序性 ,但不保障原子性。

相干定义阐明

原子性(Atomicity):即一个操作或者多个操作,要么全副执行,并且执行的过程不会被任何因素打断,要么都不执行。

有序性(Ordering):指指令在执行过程中的程序,一个操作执行在另一个操作之前或者在其执行之后。即程序执行的程序依照代码的先后顺序执行。

可见性(Visibility):指当多个线程拜访同一个变量时,一个线程批改了这个变量的值,其余线程可能立刻看失去批改的值。

volatile 实现原理

volatile 关键字在底层的实现次要是通过内存屏障(memory barrier)来实现的。内存屏障是一种 CPU 指令,用于强制执行 CPU 的外部缓存与主内存之间的数据同步。

在 Java 中,当线程读取一个 volatile 变量时,会从主内存中读取变量的最新值,并把它存储到线程的工作内存中。当线程写入一个 volatile 变量时,会把变量的值写入到线程的工作内存中,并强制将这个值刷新到主内存中。这样就保障了 volatile 变量的可见性和有序性。

在 Java 5 之后,volatile 的实现还引入了“内存屏障插入”的机制,内存屏障插入是指在指令序列中插入内存屏障以保障变量的可见性和有序性。

主内存和工作内存

Java 内存模型规定,所有的变量(实例变量和动态变量)都必须存储在主内存中,每个线程也会有本人的工作内存,线程的工作内存保留了该线程用到的变量和主内存的正本拷贝,线程对变量的操作都在工作内存中进行。线程不能间接读写主内存中的变量,如下图所示:

这样设计的目标次要是为了晋升程序的并发性能以及多线程之间的可见性问题。

主内存是 Java 虚拟机中的一块共享内存,所有线程都能够拜访。而每个线程还有本人的工作内存,线程的工作内存中存储了主内存中的变量正本的拷贝。这样做的益处是,线程之间不须要同步所有变量的读写操作,只须要同步主内存中的变量即可,这样能够进步程序的执行效率。同时,因为每个线程都有本人的工作内存,因而线程之间的变量操作相互不影响,从而进步了程序的并发性能。

内存屏障

内存屏障是一种硬件机制,用于管制 CPU 缓存和主内存之间的数据同步。在 Java 中,内存屏障通常有两种:读屏障和写屏障。

在有内存屏障的中央,会禁止指令重排序,即屏障上面的代码不能跟屏障下面的代码替换执行程序。在有内存屏障的中央,线程批改完共享变量当前会马上把该变量从本地内存写回到主内存,并且让其余线程本地内存中该变量正本生效(应用 MESI 协定)。

MESI 协定是一种缓存一致性协定,它是反对写回(write-back)缓存的最罕用协定。MESI 协定基于总线嗅探机制实现了事务串形化,也用状态机机制升高了总线带宽压力,做到了 CPU 缓存一致性。MESI 协定这 4 个字母代表 4 个状态,别离是:Modified(已批改)、Exclusive(独占)、Shared(共享)、Invalidated(已生效)。

小结

volatile 关键字在底层的实现次要是通过内存屏障(memory barrier)来实现的。内存屏障是一种 CPU 指令,用于强制执行 CPU 的外部缓存与主内存之间的数据同步。

本文已收录至《Java 面试突击》,专一 Java 面试 100 年,查看更多:www.javacn.site

退出移动版