欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java多线程高并发基础篇(五)-Java内存模型(JMM)

程序员文章站 2022-06-11 09:26:28
...

在虚拟机的规范中,定义了Java的内存模型(JMM),来屏蔽各种硬件和操作系统内存访问的差异。在JDK1.5(实现了JSR-133)发布后,Java内存模型就逐渐的完善起来了。

 

一. 并发编程要解决的关键问题

我们知道,JMM是围绕着并发过程中如何处理原子性,可见性,有序性这3个特征建立的。

1.原子性:有关原子性的内容请参考http://zhaodengfeng1989.iteye.com/blog/2418779

2.可见性:也就是线程之间以何种机制进行信息交互(也叫线程通信)。在命令式编程中,线程之间的通信的方式有两种:共享内存,消息传递。

共享内存:在共享内存的并发模型中,线程之间共享内存的共享变量,通过线程之间写-读内存中的共享变量,进行线程之间的隐式通信

消息传递:在消息传递的并发模型里,线程之间没有公共状态,通过显式发送消息的方式进行显式通信

3.有序性:也叫线程的同步,是指程序中用于控制线程间操作发生相对顺序的机制。

①在共享内存的并发模型中,需要显式的指定程序中某段代码需要互斥执行,因此线程之间的同步是显式进行的。

②在消息传递的并发模型中,由于消息发送和接收的相对顺序,线程之间的同步是隐式进行的。

 

Java的并发模型采用的是共享内存的方式,Java线程之间通过共享内存进行隐式通信,对外部完全透明,也就是我们今天看到Java内存模型。

 

二.Java内存模型的结构(也叫抽象结构)

1.线程之间如何通信

在虚拟机的体系结构中,我们知道堆内存和方法区是所有线程共享的。因此我们所说的共享内存模型,也建立在这两块区域上。因此,共享变量就是在共享内存中定义的变量,包括对象实例,静态域,数组元素。

我们来看一下JMM的抽象结构图:

Java多线程高并发基础篇(五)-Java内存模型(JMM)
            
    
    博客分类: JVM高并发JMM JMM内存模型高并发 


 从抽象出来的JMM结构看,JMM定义了线程与主内存(共享内存)之间的关系,每个线程都有一个私有的本地内存(Local Memory),在本地内存中存放着共享变量的副本。当然,线程的本地内存是JMM中抽象出来的一个概念,它涵盖了处理器的缓存,读写缓冲区,寄存器,一部分硬件以及编译器优化。

 

根据JMM的抽象结构,我们说下在共享内存的并发模型下,线程之间是如何通信的。

根据上图,我们可以知道,线程A,B之间要通信,必须要进行两步。

一是线程A把本地内存中更新过的共享变量副本刷新到主内存中;

二是线程B从主内存中读取线程A更新过的共享变量。

 

我们举一例详细说明。假设现在有两个线程,线程A,B,并且线程A,B的本地内存中都缓存了共享变量x,且x是初始状态值为0.

当线程A更新了共享变量x=1后,根据JMM的抽象结构,我们知道线程A,B之间要通信,那么需要做的第一步就是把更新后的x写入到主内存中,那么此时主内存的x=1。然后第二步线程B读取主内存中更新后的变量x=1,缓存在线程B的本地缓存中,那么此时,线程B中的共享变量x也是1(这里面涉及的机制参见帖子http://zhaodengfeng1989.iteye.com/blog/2418346)。过程见下图。

 

Java多线程高并发基础篇(五)-Java内存模型(JMM)
            
    
    博客分类: JVM高并发JMM JMM内存模型高并发 
 从以上可以看出,JMM通过控制主内存(共享内存)和线程本地内存的交互来进行线程之间的通信。

 

2.线程执行如何进行有序性操作?

从Java源代码到最后在处理器上实际执行的指令序列,会经历3种重排序。

Java多线程高并发基础篇(五)-Java内存模型(JMM)
            
    
    博客分类: JVM高并发JMM JMM内存模型高并发 
①编译器优化重排序:在不改变单线程串行语义的前提下,可以重新安排语句的执行顺序。

②指令级并行重排序:现代处理器采用了指令级并行技术(ILP,Instruction-Level-Parallelism)来将多条指令重叠执行,如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序,从而形成指令流水线

③内存系统的重排序:由于处理器使用缓存和写缓冲区,使得加载(读)和存储(写)操作看上去乱序执行。

上述①属于编译器重排序,②③属于处理器重排序。

我们一定要记住的是,

对于编译器,JMM的编译器重排序规则禁止特定类型的编译器重排序

对于处理器重排序,JMM的处理器重排序规则会要求在Java编译器生成指令序列时,插入特定类型内存屏障指令(Memory Barrier/Fence),通过特定的内存屏障指令来禁止特定类型的处理器重排序

 

下一帖我们重点说下重排序和先行发生(Happen-before)原则相关内容,他们是理解JMM的关键!!

 

 

  • Java多线程高并发基础篇(五)-Java内存模型(JMM)
            
    
    博客分类: JVM高并发JMM JMM内存模型高并发 
  • 大小: 60.4 KB
  • Java多线程高并发基础篇(五)-Java内存模型(JMM)
            
    
    博客分类: JVM高并发JMM JMM内存模型高并发 
  • 大小: 40.1 KB
  • Java多线程高并发基础篇(五)-Java内存模型(JMM)
            
    
    博客分类: JVM高并发JMM JMM内存模型高并发 
  • 大小: 17.2 KB