谈谈对Volatile的了解

  • volatile是JVM提供的轻量级的同步机制

volatile有三大个性

  1. 保障可见性
  2. 不保障原子性
  3. 禁止指令重排

JMM是什么

  • JMM(Java内存模型,简称JMM)自身是一种形象的概念并不实在存在
  • 因为JVM运行程序的实体是线程,而每个线程创立时JVM都会为其创立一个工作内存,工作内存是每个线程的公有数据区域,而Java内存模型中规定所有变量都存储到主内存,主内存是共享内存区域,所有线程都能够拜访,但线程对变量的操作必须在工作内存中进行。
  • 首先要将变量从主内存拷贝到本人的工作内存空间,而后对变量进行操作,操作实现后再将变量写回主内存,不能间接操作主内存中的变量,因而不同的线程间无法访问对方的工作内存,线程间的通信(传值)必须通过主内存来实现。

数据传输速率:硬盘 < 内存 < < cache < CPU

下面提到的概念 主内存 和 工作内存:

  • 主内存:次要包含本地办法区
  • 工作内存:属于该线程公有的栈和对主存局部变量拷贝的寄存器(包含程序计数器PC和cup工作的高速缓存区)

JMM的个性

JMM的三大个性:可见性,原子性,有序性

volatile只保障了两个,即可见性和有序性,不满足原子性

可见性(及时告诉)

  • 指的是当主内存区域中的值被某个线程写入更改后,其它线程会马上通晓更改后的值,并重新得到更改后的值。
  • 例如:有三个线程往主线程批改变量age=20,三个线程各自变量拷贝一份,其中一个线程在本人的工作空间将20改成了25,而后将工作内存中的值,写入主内存,主内存中的值被批改后,其余工作内存中的值会马上取得告诉。
用volatile验证可见性

咱们对于成员变量没有增加任何润饰时,是无奈感知其它线程批改后的值

class MyData {    // 定义int变量    int number = 0;    // 增加办法把变量 批改为 60    public void addTo60() {        this.number = 60;    }}
public class Test {    public static void main(String[] args) {        // 资源类        MyData myData = new MyData();        // 用lambda表达式创立线程        new Thread(() -> {            System.out.println("线程进来了");            // 线程睡眠三秒,假如在进行运算            try {                Thread.sleep(3000);            } catch (InterruptedException e) {                e.printStackTrace();            }            // 批改number的值            myData.addTo60();            // 输入批改后的值            System.out.println("线程更新了number的值为" + myData.number);        }).start();        // main线程就始终在这里期待循环,直到number的值不等于零        while (myData.number == 0) {        }        System.out.println("main办法完结了");    }}

最初线程没有进行,没有输入 main办法完结了 这句话,阐明没有用volatile润饰的变量,是没有可见性的。

当咱们给变量增加volatile关键字润饰:volatile int number = 0,发现能够胜利输入完结语句。

volatile 润饰的关键字,是为了减少主线程和线程之间的可见性,只有有一个线程批改了内存中的值,其它线程也能马上感知,是具备JVM轻量级同步机制的。