乐趣区

关于java:面试官我问的是Java内存模型你回答堆栈方法区干嘛

据说微信搜寻《Java 鱼仔》会变更强哦!

本文收录于 JavaStarter,外面有我残缺的 Java 系列文章,学习或面试都能够看看哦

(一)概述

很多人会把 Java 内存区域(运行时数据区)和 Java 内存模型(JMM)搞混,这两者是齐全不一样的货色。

Java 内存区域是指 JVM 运行时数据分区域存储,而 Java 内存模型是定义了线程和主内存之间的形象关系,理解 Java 内存模型是学好 Java 并发编程的根底。

(二)Java 内存模型

Java 内存模型中规定了所有的变量都存储在主内存中,每条线程还有本人的工作内存,线程对变量的所有操作都必须在工作内存中进行,而不能间接读写主内存中的变量。咱们来看一张图:

每个线程领有一个本人的公有工作内存,须要变量时从主内存中拷贝一份到工作内存,如果更新过变量之后再将共享变量刷新到主内存。

然而两个线程之间,是没有方法读取对方工作内存中的变量值的。看一个例子:

public class Test {
    private static boolean flag=false;
    public static void main(String[] args) throws InterruptedException {new Thread(new Runnable() {
            @Override
            public void run() {System.out.println("waiting");
                while (!flag){}
                System.out.println("in");
            }
        }).start();

        Thread.sleep(2000);
        new Thread(new Runnable() {
            @Override
            public void run() {System.out.println("change flag");
                flag=true;
                System.out.println("change success");
            }
        }).start();}
}

首先定义了一个动态变量 flag 为 false,A 线程期待 flag 等于 true 后输入 in,于是咱们新开一个线程将 flag 批改为 true。后果是 A 线程仍旧无奈输入 in。

原理看 Java 内存模型的图就了解了,不同的线程批改变量,对本地线程是不可见的。

(三)JMM 数据的原子操作

通过下面这段代码,咱们曾经晓得了 Java 内存模型的构造,那么工作内存和主内存之间是如何读取变量又是如何批改变量的呢?JMM 提供了对变量的一系列原子操作。咱们先不讲实践,看个图,这个图形容了下面一段代码的执行过程:

整个过程一共十步,反复几个步骤不讲了,我把不反复的六个操作列一下:

read:从主内存读取数据

load:将主内存读取到的数据写入工作内存

use:从工作内存中读取数据来应用

assign:把计算好的值从新赋值到工作内存中

store:将工作内存数据写入主内存

write:将 store 过来的变量赋值给主内存中的变量

通过下面的图,对上面六个原子操作的了解应该能够更加粗浅了。JMM 的原子操作一共有八个,上面列出剩下的两个

lock:将主内存变量加锁,标识为线程独占状态

unlock:将主内存变量解锁,解锁后其余线程能够锁定该变量

(四)JMM 缓存不统一问题

从后面的例子咱们曾经看到了,一个线程批改完数据,另外一个线程无奈立刻可见,这就是 JMM 缓存不统一的问题,有两种解决办法:

加锁:

还记得咱们没有用到过的 JMM 原操作的最初两个吗,lock 和 unlock,应用这两个操作就能够实现缓存一致性,一个线程想要获取某个主内存变量时,先应用 lock 将主内存变量加锁,只有他能力应用,等用完后再 unlock,其余线程能力竞争。然而加锁意味着性能低。

MESI 缓存一致性协定:

这个协定波及到 cpu 的 总线嗅探机制 ,从下面的 JMM 执行的流程图中咱们能够看到当某个线程批改了共享变量后,他会回写到主内存,MESI 缓存一致性协定就是通过 cpu 的总线嗅探机制, 将其余也正在应用该变量的线程的数据生效掉,使得这些线程要从新读取主内存中的值,从而保障缓存最终一致性。(volatile 的实现原理)

(五)总结

Java 内存模型在多并发中非常重要,包含前面学习 volatile 或者 synchronized 这个关键字的时候,都会回到这个 Java 内存模型中。

退出移动版