如今,我们正处于一个新兴技术飞速发展的时代,各行各业对开发者的要求也越来越高。因此无论是入门阶段还是进阶阶段,都需要学习大量的专业知识,需要不断提高对Java的理解。无论是求职面试还是实际项目开发,volatile都是需要掌握的知识点。今天就让我们一起来认识一下volatile机制,从实战中提升自己的能力。什么是挥发性的?为什么使用挥发性?Java是一种面向对象的高级编程语言。Java语言包含两种固有的同步机制:同步块(或方法)和易变变量。Volatile是Java机制提供的轻量级同步。Java多线程的发展具有三个特点:原子性、可见性和有序性。使用volatile不会引起线程上下文切换和调度,可以保证内存可见性,防止指令重排序。基本用法在Java语言中,volatile关键字用于修饰变量,如下所示。表示:该变量需要直接存放在主存中。publicclassSharedClass{publicvolatileintcounter=0;}volatile关键字修饰的int计数器变量会直接存入主存。并且所有对该变量的读操作都会直接从主存中读取,而不是直接从CPU缓存中读取。理解volatile关键字对于初学者来说,volatile只是一个简单的认识。他们只知道volatile的作用是“保证可见性”和“禁止指令重排序”,但还是存在一些误解。变量可见性问题(VariableVisibilityProblem):volatile可以保证变量变化在多个线程间的可见性。在多线程应用中,为了计算性能,每个线程默认都会将变量从主存中复制到线程所在CPU的缓存中,然后进行读写操作。现在的电脑基本上都是多核CPU。不同的线程可能运行在不同的核心上,每个核心都会有自己的缓存空间。volatile的出现就是为了解决线程间的不可见性。被volatile修改的变量将在线程之间变得可见。解决多线程不可见的方法是:被volatile修饰的变量,所有对该变量的读操作都会直接从主存中读取,而不是从CPU自身的缓存中读取。所有对该变量的写入都将写入主内存。因为主存是所有CPU共享的,当然即使是不同CPU上的线程也能看到其他线程对这个变量的修改。volatile不仅仅保证了volatile变量的可见性,volatile在可见性上做的工作比保证volatile变量的可见性还多。特点与原则(1)可见性如果任何线程修改了一个volatile修饰变量,其他线程可以立即识别出最新的值。实现可见性的原理如下。第一步:修改本地内存,强制闪回主存。第二步:强制使其他线程的工作内存失效。(这部分多属于MESI协议)(2)互斥只允许一个线程同时操作volatile变量。volatile修饰的变量在没有加锁的场景下也可以达到加锁的效果,类似于互斥锁。上面的VolatileFeaturesA.java和下面的VolatileFeaturesB.java实现的功能一样(getAndAdd方法除外)。(3)偏序JVM使用内存屏障来禁止指令重排,从而达到偏序的效果。知道了内存屏障的类型,我们就可以解决重排序带来的顺序问题。什么是内存屏障?内存屏障其实就是一条CPU指令,在硬件层面可以分为两种:LoadBarrier和StoreBarrier,即readbarrier和writebarrier。主要有两个作用:防止屏障两边的指令重新排序;强制将写缓冲区/缓存中的脏数据写回主存,并使缓存中的相应数据失效。在JVM层面,功能同上,但类型可以分为四种:顺序实现原则:如果属性被volatile修饰,会在属性前后插入内存屏障来禁止它在编译期间。命令重排。首先,一个变量被volatile关键字修饰后,有两个作用:对于写操作:变量被改变后,必须立即写回主存。对于读取操作:读取变量时,从主存而不是缓存中读取。
