内存模型概述

1. 引言

并发的两个关键问题:

  1. 线程之间以何种机制来交换信息?
  2. 线程以何种机制来控制不同线程间操作发生的相对顺序?

2. 并发模型

有两种并发编程模型可以解决以上两个问题:

  • 消息传递并发模型
  • 共享内存并发模型

两并发模型的区别如下:

通信同步
消息传递并发模型线程之间没有公共状态,线程之间的通信必须通过发送消息来显示进行通信发送消息天然同步,因为发送消息总是在接受消息之前,因此它们的同步是隐式的。
共享内存并发模型线程之间的共享程序的公共状态,通过读写内存中的公共状态进行隐式通信。必须显示指定某段代码需要在线程之间互斥执行,因此同步是显示的。

Java 中使用的是共享内存并发模型。


3. 内存模型

3.1 内存划分

在这里插入图片描述
对于每一个线程来讲,栈是私有的,堆是共享的。

也就是说在栈中的局部变量,方法定义参数,异常处理器参数不会在线程中共享,也就没有下文所讲的内存可见性问题,也不受内存模型影响。

所以,内存可见性针对的是堆中的变量(共享变量)。

3.2 内存可见性

现代计算机为了高效,往往会在闪存中缓存共享变量,因为闪存的速度比内存快得多且更加高效。

线程之间的共享变量存储在主内存(闪存)中,每个线程都拥有自己的本地内存,存储了该线程读写变量的副本。
本地内存是Java内存模型的一个抽象概念,它并不真实存在。
本地内存覆盖了缓存,写缓冲区,寄存器等。

Java 的线程之间通信由 JMM(Java Memory Manager)控制,从抽象的角度来说 JMM 定义了线程和主内存之间的抽象关系。

在这里插入图片描述

图中所需要关注的点:

  1. 所有的共享变量存储在主内存中
  2. 所有的线程都保存了一份共享变量的副本

如果线程A 与 线程B 要通信的话,必须经历如下两个步骤:

  1. 线程A 将本地内存更新过的值刷新(同步)到主内存中
  2. 线程B 到主内存中读取 线程A 已更新过的共享变量

所以,线程之间通信必须通过主内存。

JMM 规定,线程对共享变量的操作必须在自己的本地内存中进行,不能直接从主内存中读写。

线程B 并不是直接从主内存中读取变量的值,而是先在本地内存找到这个共享变量,如果发现这个共享变量已经被更新了,那么 线程B 的本地内存就会从主内存中读取这个共享变量的新值,并拷贝到本地内存中,最后 线程B 再读取本地内存中的新值。

在这里插入图片描述

那么如何知道这个共享变量是否已被其它线程更新了呢?这就是前文所提到的 JMM 功劳了,也是 JMM 存在的重要性之一。JMM 通过控制主内存与每个线程的本地内存之间的交互,来提供内存可见性。

3.3 JMM与内存划分的区别与联系

区别:
概念上的不同,JMM是抽象的,它用来描述一种规则,通过这个规则可以用来控制变量的访问方式。围绕原子性,有序性,可见性等展开的。而 Java 运行内存划分是具体的,是 JMM 运行 Java 程序时必要的内存划分。


联系:
都存在私有数据区域和共享数据区域。⼀般来说,JMM中的主内存属于共享数据区域,他是包含了堆和⽅法区;同样,JMM中的本地内存属于私有数据区域,包含了程序计数器、本地⽅法栈、虚拟机栈。


实际上,他们表达的是同⼀种含义。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值