`
春花秋月何时了
  • 浏览: 39413 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Java内存模型JMM之一内存交互操作

 
阅读更多

为了能够深入理解Java并发的原理,以及synchronized、volatile和Lock等内部原理,我们首先需要了解Java内存模型的相关知识。

 

一、从硬件的效率与一致性开始的硬件内存架构

 由于计算机的运算速率和它的存储和通讯子系统速度的差距太大,现代计算机硬件已经从追求处理器频率发展到多核心并发处理的过程。但是计算机的运算任务又不可能只靠处理器以及处理器内的寄存器“计算”就能完成,处理器至少需要与内存进行交互,从而读取运算数据,存储运算结果。由于计算机的存储设备与处理器的运算速度之间有着几个数量级的差距,所以现代计算机不得不加入一层读写速度尽可能接近处理器运算速度的高速缓存(Cache)来作为内存与处理器之间的缓冲。处理器将计算需要的数据复制到缓存中,是运算能够快速进行,当运算结束再从缓存同步回内存。在多处理器系统中,每个处理器都有各自的高速缓存,并且又共享同一主内存,当多个处理器的运算都涉及到同一块主内存区域时,将可能导致各自的缓存数据不一致,为了解决一致性问题,各个处理器访问缓存时都需要遵循特定的缓存一致性协议。如图所示:

同时为了使得处理器充分被利用,处理器可能会对输入代码进行乱序执行(Out-Of-Order Execution)优化,并在计算后将乱序执行的结果重组,保证结果与顺序执行一致。Java虚拟机的即时编译器也有类似的指令重排序(Instruction Reorder)优化

因此,若一个计算任务依赖另一计算任务的中间结果,那其顺序性,不能靠代码的先后顺序来保证。 

 

二、Java内存模型

Java内存模型(Java Memory Model, JMM)的主要目标是定义程序中各个变量的访问规则即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。此处的变量包括了实例字段、静态字段和构成数组对象的元素,但是不包括局部变量和方法参数,因为它们是线程私有的,不会被共享也就不存在竞争问题。

 

2.1 JVM内部存储结构---堆、线程栈

       Java内存模型把Java虚拟机内部划分为线程栈。如下图所示:

    栈是运行时的单位,而堆是存储的单位。在Java中每一个运行在Java虚拟机里的线程都拥有自己的线程栈一个线程仅能访问自己的线程栈。一个线程创建的本地变量对其它线程不可见,即使两个线程执行的是同一段代码,它们也会在各自的线程栈中创建各自的本地变量。

    1. 所有的基本类型的本地变量和对象引用都存放在栈中,因此对其它线程不可见。一个线程可能向另一个线程传递一个基本类型变量的拷贝,但是它不能共享这个基本类型变量自身。

    2. 对象都存放在堆中,包括基本类型的对象版本。如果一个对象被创建然后赋值给一个局部变量,或者用来作为另一个对象的成员变量,这个对象任然是存放在堆上。

    3. 一个本地变量也可能是指向一个对象的一个引用。在这种情况下,引用(这个本地变量)存放在线程栈上,但是对象本身存放在堆上。

    4. 一个对象可能包含方法,这些方法可能包含本地变量。这些本地变量任然存放在线程栈上,即使这些方法所属的对象存放在堆上。

    5. 一个对象的成员变量可能随着这个对象自身存放在堆上。不管这个成员变量是原始类型还是引用类型。

    6. 静态成员变量跟随着类定义一起也存放在堆上。

    7. 存放在堆上的对象可以被所有持有对这个对象引用的线程访问。当多个线程通过调用同一个对象的相同方法访问其成员变量的时候,每个线程都将拥有该成员变量的拷贝而不是其自身。

 

Java虚拟机内部的这种堆/栈存储结构显然与计算机的硬件内存架构之间存在差异,从硬件上来看,不管是堆还是栈,大部分数据都存在主内存中,还有一部分可能会存到处理器寄存器和高速缓存中,这种交叉对应关系如下图所示:  

 

2.2 Java内存模型---主内存、工作内存

    Java内存模型从另一个层面还规定了,所有的变量都存储在主内存中,每条线程还有自己的工作内存,这里的主内存并不是上面的硬件内存架构中的主内存,而只是Java虚拟机内存的一部分,当然两者可以互相类比。而且工作内存也可以和硬件内存架构中的高速缓存类比,它们确有相似之处,另外这里的主内存和工作内存的划分与上面的堆/栈划分并不是同一个层面的,两者基本没有关系。

    线程对变量的所有操作(读取、赋值等)都必须在各自的工作内存中进行,而不能直接操作主内存中的变量本身,也即线程的工作内存中保存了被该线程使用到的位于主内存中变量的副本拷贝。不同的线程无法直接访问对方工作内存中的变量,线程间变量值的传递都需要通过主内存来完成,线程、工作内存、主内存三者的交互关系如下图所示:

如图所示,Java内存模型定义了8种操作来完成Java线程操作一个变量的实现细节,不同平台的虚拟机在实现这些操作时必须保证每一个操作都是原子的,不可再分的(对于long,double类型的变量在某些平台可以例外)。
 

  • lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态。
  • unlock(解锁):作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
  • read(读取):作用于主内存变量,把一个变量值从主内存传输到线程的工作内存中,以便随后的load动作使用。
  • load(载入):作用于工作内存的变量,它把通过read操作从主内存中得到的变量值放入工作内存的变量副本中。
  • use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作。
  • assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
  • store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传送到主内存中,以便随后的write的操作使用。
  • write(写入):作用于主内存的变量,它把通过store操作从工作内存中得到的变量的值放入主内存的变量中。

通过上面的内存交互规则,如果要把一个变量从主内存复制到工作内存, 就需要顺序的执行read和load操作,而如果要把一个变量从工作内存同步回主内存,则需要顺序执行store和write操作,注意是顺序执行,而不是连续执行,也就是两个操作之间可以插入其他操作。除此之外,Java内存模型对这8中操作进行操作的其他约束:

 

  1. 不允许read和load、store和write操作之一单独出现。
  2. 不允许线程丢弃它的最近的assign操作,即变量在工作内存中改变之后,必须同步回主内存。
  3. 不允许线程把没有经过assign操作的变量,同步回主内存。
  4. 一个新的变量只能在主内存中诞生,即对一个变量进行use、store操作之前,必须先执行过load、assign操作。
  5. 一个变量在同一时刻只能被一条线程执行lock操作,一旦lock成功,可以被同一线程重复lock多次,多次执行lock之后,只有执行相同次数的unlock操作,变量才会被解锁。
  6. 对一个变量执行lock操作,将会清空工作内存中该变量的值,所以在执行引擎使用这个变量前,需要重新执行load或assign操作对其进行初始化。
  7. 对一个变量执行unlock操作之前,必须先把该变量同步回主内存(执行store、write操作)。
  8. 如果一个变量事先没有被lock操作锁定,那就不允许对它执行unlock操作,也不允许unlock一个被其他线程lock的变量。
  • 大小: 4.4 KB
  • 大小: 24.5 KB
  • 大小: 58 KB
  • 大小: 36.5 KB
分享到:
评论

相关推荐

    java内存模型jmm

    java内存模型jmm

    Java内存模型详解JMM.docx

    Java内存模型详解JMM.docx

    深入Java内存模型-JMM

    深入Java内存模型-JMM。。。。。。。。。。。。。。。。。。

    深入理解 Java 内存模型

    深入理解 Java 内存模型,由程晓明编著,深入理解java内存模型JMM

    java内存模型JMM(Java Memory Model)1

    由于JVM运行程序的实体是线程,而每个线程创建时JVM都会为其创建一个工作内存(有些地方称为栈空间),工作内存是每个线程的私有数据区域,而Java内存模型中规定

    《深入理解JAVA内存模型》PDF

    Java线程之间的通信由Java内存模型(本文简称为JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main ...

    深入理解java内存模型

    Java内存模型的抽象 重排序 处理器重排序与内存屏障指令 happens-before 重排序 数据依赖性 as-if-serial 语义 程序顺序规则 重排序对多线程的影响 顺序一致性 数据竞争与顺序一致性保证 顺序一致性内存模型 同步...

    深入理解Java内存模型.程晓明(带书签文字版).pdf

    Java 内存模型的抽象 4 重排序 6 处理器重排序与内存屏障指令 7 happens-before 10 重排序 13 数据依赖性 13 as-if-serial 语义 13 程序顺序规则 15 重排序对多线程的影响 15 顺序一致性 19 数据竞争与顺序...

    Java内存模型JMM浅析

    Java Memory Model简称JMM, 是一系列的Java虚拟机平台对开发者提供的多线程环境下的内存可见性、是否可以重排序等问题的无关具体平台的统一的保证。(可能在术语上与Java运行时内存分布有歧义,后者指堆、方法区、...

    Java内存模型JMM详解

    主要介绍了Java内存模型JMM详解,涉及volatile和监视器锁,final字段,内存屏障等相关内容,具有一定参考价值,需要的朋友可以了解下。

    深入理解Java内存模型

    Agenda: •什么是Java内存模型JMM •内存可见性 •有序性 •指令重排序 •内存屏障 •顺序一致性与Happens-before规则 •volatile, synchronized, 原子变量,锁, final的原理

    深入理解Java内存模型(经典).rar

    深入理解Java内存模型

    学习Java内存模型JMM心得

    主要介绍了学习Java内存模型JMM的心得以及对其原理做了深入的介绍,有兴趣的朋友学习下吧。

    java内存模型(JMM).docx

    这时就存在一个问题:由于 CPU 执行速度很快,而从内存读取数据和向内存写入数据的过程跟 CPU 执行指令的速度比起来要差几个数量级,因此如果任何时候对数据的操作都要通过和内存的交互来进行,会大大降低指令执行的...

    JMM内存模型图

    Java运行时内存模型图

    java内存模型的介绍和说明

    介绍java的内存管理方式和特点 1.JMM 简介 2.堆和栈 3.本机内存 4.防止内存泄漏

    JMM(Java内存模型)及Volatile底层实现原理.md

    Java内存模型及Volatile底层实现原理

    Java内存模型案例讲解.docx

    Java线程之间的通信由Java内存模型简称JMM(Java Memory Mode)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM是这样定义线程和主内存之间的抽象关系的:线程之间的共享变量...

Global site tag (gtag.js) - Google Analytics