被JAVA内存模型绕晕了?看来看这一篇


前言

网上有很多关于JAVA内存模型的文章,但大多只讲解了JAVA内存模型本身的概念,很少提到JAVA内存模型出现的原因是什么,导致看完之后自己的思维更加混乱。本文简单介绍为什么要有内存模型以及JAVA内存模型的基本概念供参考学习。


一、为什么要有内存模型

1.1 CPU和缓存一致性

我们应该都知道,计算机在执行程序的时候,每条指令都是在CPU中执行的,而执行的时候,又免不了要和数据打交道。而计算机上面的数据,是存放在主存当中的,也就是计算机的物理内存。

刚开始,还相安无事的,但是随着CPU技术的发展,CPU的执行速度越来越快。而由于内存的技术并没有太大的变化,所以从内存中读取和写入数据的过程和CPU的执行速度比起来差距就会越来越大,这就导致CPU每次操作内存都要耗费很多等待时间。

例如:你是cpu,小伙伴是内存,刚开始你和你的小伙伴其乐融融,后来你读到了博士,你的每一个命令,由于小伙伴的理解能力和执行能力欠缺,就会耗费很多时间,这就无形拖慢了效率。

可是,不能因为内存的读写速度慢,就不发展CPU技术了吧,总不能让内存成为计算机处理的瓶颈吧。

解决办法:
在CPU和内存之间增加高速缓存。缓存的概念大家都知道,就是保存一份数据拷贝。他的特点是速度快,内存小,并且昂贵。

那么,程序的执行过程就变成了:
当程序在运行过程中,会将运算需要的数据从主存复制一份到CPU的高速缓存当中,那么CPU进行计算时就可以直接从它的高速缓存读取数据和向其中写入数据,当运算结束之后,再将高速缓存中的数据刷新到主存当中。

但是这会出现什么问题?
在CPU和主存之间增加缓存,在多线程场景下就可能存在缓存一致性问题,也就是说,在多核CPU中,每个核的自己的缓存中,关于同一个数据的缓存内容可能不一致。
在这里插入图片描述

1.2线程切换和指令重排

Java 并发程序都是基于多线程的,自然也会涉及到任务切换,任务切换的时机大多数是在时间片结束的时候。这种切换可能会导致问题。
两个线程 A 和 B 同时执行 count++, 即便 count 使用 volatile 修辞,我们预期的结果值是 2,但实际可能是 1。
在这里插入图片描述
编译器为了优化性能,有时候会改变程序中语句的先后顺序,比如Java虚拟机的即时编译器(JIT)也会做指令重排。
如果任由处理器优化和编译器对指令重排的话,就可能导致各种各样的问题。
在这里插入图片描述

1.3并发编程的核心问题

原子性是指在一个操作中就是cpu不可以在中途暂停然后再调度,既不被中断操作,要不执行完成,要不就不执行。
可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
有序性即程序执行的顺序按照代码的先后顺序执行。

缓存一致性问题其实就是可见性问题。而线程切换是可以导致原子性问题的。指令重排即会导致有序性问题。


二、JAVA内存模型(JMM)

前面提到的,缓存一致性问题、指令重排问题是硬件的不断升级导致的。那么,有没有什么机制可以很好的解决上面的这些问题呢?
为了保证并发编程中可以满足原子性、可见性及有序性。有一个重要的概念,那就是——内存模型。

Java内存模型(Java Memory Model ,JMM)就是一种符合内存模型规范的,屏蔽了各种硬件和操作系统的访问差异的,保证了Java程序在各种平台下对内存的访问都能保证效果一致的机制及规范。

JMM就作用于工作内存和主存之间数据同步过程。他规定了如何做数据同步以及什么时候做数据同步。
在这里插入图片描述


三、JAVA内存模型的实现

Java内存模型封装了底层的实现后提供给程序员使用的一些关键字:比如volatile、synchronized、final、concurrent包等。
原子性:在Java中,为了保证原子性,提供了两个高级的字节码指令monitorenter和monitorexit。在synchronized的实现原理文章中,介绍过,这两个字节码,在Java中对应的关键字就是synchronized。

可见性:Java中的volatile关键字提供了一个功能,那就是被其修饰的变量修改后将新值同步回主内存,变量读取前从主内存刷新变量值。因此,可以使用volatile来保证多线程操作时变量的可见性。

有序性:在Java中,可以使用synchronized和volatile来保证多线程之间操作的有序性。volatile关键字会禁止指令重排,synchronized关键字保证同一时刻只允许一条线程操作。


总结

JMM是一种规范,目的是解决由于多线程通过共享内存进行通信时,存在的本地内存数据不一致、编译器会对代码指令重排序等带来的问题。除了定义了一套规范,还提供了一系列原语,封装了底层实现后,供开发者直接使用。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JinziH Never Give Up

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值