Java内存模型的基础

并发编程模型的两个关键问题

线程之间如何通信
通信是指线程之间以何种机制来交换信息。在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递
共享内存的并发模型里,线程之间共享程序的公共状态,通过写-读内存中的公共状态进行隐式通信。
消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过发送消息来显式进行通信。
线程之间如何同步(这里的线程是指并发执行的活动实体)
同步是指程序中用于控制不同线程间操作发生相对顺序的机制
共享内存并发模型里,同步是显式进行的。
消息传递的并发模型里,由于消息的发送必须在消息的接收之前,因此同步是隐式进行的。
Java的并发采用的是共享内存模型,Java线程之间的通信总是隐式进行,整个通信过程对程序员完全透明。

Java内存模型的抽象结构

在Java中,所有实例域、静态域和数组元素都存储在堆内存中,堆内存在线程之间共享,局部变量,方法定义参数和异常处理器参数不会在线程之间共享,它们不会有内存可见性问题,也不受内存模型的响。
Java线程之间的通信由Java内存模型(本文简称为JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。
线程之间的共享变量存储在主内存中,每一个线程都有一个私有的内地内存,本地内存中存储了该线程以读/写共享变量的副本,本地内存并不真实存在
Java内存模型(JMM)---java并发编程的艺术(三)
线程的通信步骤
线程 A 把本地内存 A 中更新过的共享变量刷新到主内存中去
线程 B 到主内存中去读取线程 A 之前已更新过的共享变量
Java内存模型(JMM)---java并发编程的艺术(三)
从整体来看,这两个步骤实质上是线程A在向线程B发送消息,而且这个通信过程必须要经过主内存。JMM通过控制主内存与每个线程的本地内存之间的交互,来为Java程序员提供内存可见性保证。


从源代码到指令序列的重排序

什么是重排序
重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新拍的一种手段
在执行程序时,为了提高性能,编译器和处理器常常会对指令做重排序。
重排序分3种类型。
1)编译器优化的重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。
2)指令级并行的重排序。现代处理器采用了指令级并行技术来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
3)内存系统的重排序。由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。
从Java源代码到最终实际执行的指令序列,会分别经历下面3种重排序Java内存模型(JMM)---java并发编程的艺术(三)
1属于编译器重排序,2和3属于处理器重排序

重排序的禁止
对于编译器,JMM 的编译器重排序规则会禁止特定类型的编译器重排序(不是所有的编译器重排序都要禁止)
对于处理器,JMM 的处理器重排序规则会要求 Java 编译器在生成指令序列时,插入特定类型的内存屏障指令,通过内存屏障指令来禁止特定类型的处理器重排序
JMM属于语言级的内存模型,它确保在不同的编译器和不同的处理器平台之上,通过禁止特定类型的编译器重排序和处理器重排序


并发编程模型的分类

现代的处理器使用写缓冲区临时保存向内存写入的数据。通过以批处理的方式刷新写缓冲区,以及合并写缓冲区中对同一内存地址的多次写,减少对内存总线的占用。虽然写缓冲区有这么多好处,但每个处理器上的写缓冲区,仅仅对它所在的处理器可见。这个特性会对内存操作的执行顺序产生重要的影响:处理器对内存的读/写操作的执行顺序,不一定与内存实际发生的读/写操作顺序一致! 由于写缓冲区仅对自己的处理器可见,它会导致处理器执行内存操作的顺序可能会与内存实际的操作执行顺序不一致。由于现代的处理器都会使用写缓冲区,因此现代的处理器都会允许对写-读操作进行重排序。
为了保证内存可见性,Java编译器在生成指令序列的适当位置会插入内存屏障指令来禁止特定类型的处理器重排序。
JMM把内存屏障指令分为4类
Java内存模型(JMM)---java并发编程的艺术(三)
StoreLoad Barriers是一个“全能型”的屏障,它同时具有其他3个屏障的效果。现代的多处
理器大多支持该屏障(其他类型的屏障不一定被所有处理器支持)。执行该屏障开销会很昂
贵,因为当前处理器通常要把写缓冲区中的数据全部刷新到内存中

happens-before简介

使用happens-before的概念来阐述操作之间的内存可见性。
在JMM中,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在happens-before关系。这里提到的两个操作既可以是在一个线程之内,也可以是在不同线程之间。Java内存模型(JMM)---java并发编程的艺术(三)


这几天把这本《Java并发编程的艺术》给看的一半了,发现了很多知识,每天看书,定时总结,加油!

相关文章:

  • 2021-10-08
  • 2021-06-30
  • 2021-10-17
  • 2022-01-07
  • 2021-09-08
  • 2021-04-30
  • 2022-01-01
  • 2021-09-25
猜你喜欢
  • 2021-12-05
  • 2021-05-05
  • 2021-08-07
  • 2021-11-10
  • 2021-07-11
  • 2021-10-29
  • 2021-10-15
相关资源
相似解决方案