乐趣区

关于java:1Volatile和JMM内存模型的可见性

谈谈对 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 轻量级同步机制的。

退出移动版