Bootstrap

volatile详解

1.什么是volatile?

volatile是java虚拟机提供的轻量级的同步机制,一共有三大特性,保证可见性,不保证原子性,禁止指令重排。

2.可见性

首先提一个JMM的概念,JMM是Java内存模型,它描述的是一组规范或规则,通过这组规范定义了程序中各个变量(实例字段,静态字段和构成数组对象的元素)的访问方式。JMM规定所有的变量都在主内存,主内存是公共的所有线程都可以访问,线程对变量的操作必须是在自己的工作内存中。在这个过程中可能出现一个问题。

在这里插入图片描述

现在假设主物理内存中存在一个变量他的值为7,现在线程A和线程B要操作这个变量所以他们首先要将这个变量的值拷贝一份放到自己的工作内存中,如果A将这个值改为1,这时候线程B要使用这个变量但是B线程工作内存中的变量副本是7不是新修改的1这就会出现问题。所以JMM规定线程解锁前一定要将自己工作内存的变量写回主物理内存中,线程加锁前一定要读取主物理内存的值。也就是说一旦A修改了变量值,B马上能知道并且能更新自己工作内存的值。这就是可见性。

3.volatile可见性代码证明

volatile可以保证可见性,及时通知其他线程,主物理内存的值已经被修改。我们用代码证明一下。

设计思路首先我们新建一个类里面有一个number,然后写一个方法可以让他的值变成60,这时候在主线程中开启一个新的线程让他3s后将number值改为60然后主线程写一个循环如果主线程能立刻监听到number值的改变则主线程输出改变后的值此时说明有可见性。如果一直死循环说明主线程没有监听到number值的更改说明不具有可见性。

class MyData{
   
    public int number = 0;
    public void change(){
   
        number = 60;
    }
}

public class VolatileTest {
   
    public static void main(String[] args) {
   
        MyData myData = new MyData();
        new Thread(()->{
   
            System.out.println(Thread.currentThread().getName() + "number is :"+ myData.number);
            try {
   
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
   
                e.printStackTrace();
            }
            myData.change();
            System.out.println(Thread.currentThread().getName() + "has changed" + myData.number);
        },"A").start();
        while(myData.number == 0){
   

        
;