java 内存模型

java 内存模型

JMM 即 Java Memory Model,它定义了主存、工作内存抽象概念。

JMM 体现在以下几个方面

  • 原子性 - 保证指令不会受到线程上下文切换的影响
  • 可见性 - 保证指令不会受 cpu 缓存的影响
  • 有序性 - 保证指令不会受 cpu 指令并行优化的影响

可见性

main 线程对 run 变量的修改对于 t 线程不可见,导致了 t 线程无法停止:

private static boolean run = true;

    public static void main(String[] args) {

        Thread t = new Thread(() -> {
            while (run) {
                // 死循环 一直占用 CPU 
                // 如果去掉 下面注释,将无法看到 效果 (猜测可能是 下面的方法无法一直占用CPU)
                // System.out.println("循环");
            }
        });
        t.start();


        Sleep.sleep(1);
        // 循环不会停下
        run = false;
    }
  1. 初始状态,t 线程刚开始从主内存读取了 run 的值到工作内存。

在这里插入图片描述

  1. 因为 t 线程要频繁从主内存中读取 run 的值,JIT 编译器会将 run 的值缓存至自己工作内存中的高速缓存中, 减少对主存中 run 的访问,提供频率。

在这里插入图片描述

  1. 1秒之后,main 线程修改了 run 的值,并同步至主存,而 t 是从自己工作内存中的高速缓存中读取这个变量的值,结果永远是旧值

在这里插入图片描述

线程的工作内存

线程的工作内存(working memory) 只是对 cpu 的寄存器和高速缓存的抽象描述。它并不是线程的栈。

内存一致性解决方法

volatile

它可以用来修饰成员变量和静态成员变量,他可以避免线程从自己的工作缓存中查找变量的值,必须到主存中获取它的值,线程操作 volatile 变量都是直接操作主存

有序性

JVM 会在不影响正确性的前提下,可以调整语句的执行顺序

static int i;
static int j;

// 在某个线程内执行如下赋值操作
i = 5;
j = 3;

可以看到,至于是先执行 i 还是先执行 j,对最终的结果不会产生影响。所以执行顺序可能是

i = 5;
j = 3;

也可以是

j = 3;
i = 5;

这种特性称之为 【指令重排】,多线程下【指令重排】可能会影响正确性。为什么要有重排,这是依据计算机底层的执行指令的原理。

int num = 0;
boolean ready = false;

// 线程1 执行此方法
public void actor1(IResult r) {
	if(ready) {
		r.r1 = num + num;
	}else {
		r.r1 = 1;
	}
}

// 线程2 执行此方法
public void actor2(IResult r) {
	num = 2;
	ready = true;
}

class IResult {
    public int r1;
}

可能的结果有【这里基本可以不用考虑可见性问题】:

情况1:线程1 先执行 结果为 1

情况2:线程2 先执行 num = 2,但没来得及执行 ready = true ,线程1 执行,还是进入 else 分支,结果为 1

情况3:线程2 执行到 ready = true,线程 1 执行,这回进入 if 分支,结果为 4

情况 为 4

线程2 执行 ready = true ,切换到线程1,进入 if 分支,相加为0,再切回线程2 执行 num = 2

这种现象叫指令重排,是 JIT 编译器在运行是的一些优化。

解决方法

volatile 修饰的变量,可以禁用指令重排

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值