Java内存模型JMM(五)

JMM即java内存模型(Java Memory Model)。它定义了java虚拟机(JVM)在计算机内存中的工作方式。JVM是整个计算机虚拟模型,所有JMM隶属于JVM。从抽象角度来看,JMM定义了线程和组内存之间的抽象关系,线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,本地内存中存储了该线程以读/写共享变量的副本。本地内存是JVM的一个抽象概念,并不是真实存在。它涵盖了缓存,写缓冲区,寄存器以及其它的硬件和编译器优化。

简而言之,JMM用来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各平台下都能够达到一致的内存访问效果。

JVM在设计时候考虑到,如果JAVA线程每次读取和写入变量都直接操作主内存,对性能影响比较大,所以每条线程拥有各自的工作内存,工作内存中的变量是主内存中的一份拷贝,线程对变量的读取和写入,直接在工作内存中操作,而不能直接去操作主内存中的变量。但是这样就会出现一个问题,当一个线程修改了自己工作内存中变量,对其他线程是不可见的,会导致线程不安全的问题。因为JMM制定了一套标准来保证开发者在编写多线程程序的时候,能够控制什么时候内存会被同步给其他线程。

内存交互操作(8种)

     1. lock(锁定) - 作用于主内存的变量,它把一个变量标识为一条线程独占的状态。

     2. unlock(解锁) - 作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可能被其他线程锁定。

     3. read(读取) - 作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的load动作使用。

     4. load(载入) - 作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。

     5. use(使用) - 作用于工作内存的变量,它把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用到变量的值的字节码指令时将会执行这个操作。

    6. assign(赋值) - 作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存的变量,每当虚拟朵遇到一个给变量赋值的字节码指令时执行这个操作。

   7. store(存储) - 作用于工作内存的变量,它把工作内存中一个变量的值传送到主内存中,以便随后的write操作使用。

   8. write(写入) - 作用于主内存的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中。

JMM对这八种指令的使用,制定了如下规则

  • 不允许read和load、store和write操作之一单独出现,即不允许一个变量从主内存读取了但工作内存不接受,或者从工作内存发起回写了但主内存不接受的情况出现。
  • 不允许线程丢弃它最近的assign操作,即工作变量的数据改变了之后,必须告知主存。
  • 不允许一个线程将没有assign的数据从工作内存同步回主内存。
  • 一个新的变量必须在主内存中"诞生",不允许工作内存直接使用一个未被初始化(assign或load)的变量。
  • 一个变量同一时间只有一个线程能对其进行lock。多次lock后,必须执行相同次数的unlock才能解锁。
  • 如果对一个变量进行lock操作,会清空所有工作内存中此变量的值,在执行引擎使用这个变量前,必须重新load或assign操作初始化变量的值。
  • 如果一个变量没有被lock,就不能对其进行unlock操作。也不能unlock一个被其他线程锁住的变量。
  • 对一个变量进行unlock操作之前,必须把此变量同步回主内存(执行store和write操作)。

JMM对这八种操作规则和对volatile的一些特殊规则就能确定哪些操作是线程安全,哪些操作是线程不安全的了。但是这些规则实在复杂,很难在实践中直接分析。所以一般我们也不会通过上述规则进行分析。更多的时候,使用java的happen-before规则来进行分析。 

模型特征

原子性(Atomicity)

由Java内存模型来直接保证的原子性变量操作包括read、load、assign、use、store和write这六个,我们大致可以认为基本数类型的访问读写是具备原子性的。如果需要一个更大范围的原子性保证,sychronized关键字同步块提供了这类操作(隐式插入字节码指令monitorenter和monitorexit)。

可见性(Visibility)

可见性是指当一个线程修改了共享变量的值,其他线程能够立即得知这个修改。JMM在变量修改后将新值同步回主内存,依赖主内存作为媒介,在变量被线程读取前从内存刷新变量新值,保证变量的可见性。普通变量和volatile变量都是如此,只不过volatile的特殊规则保证了这种可见性是立即得知的,而普通变量并不具备这种严格的可见性。除了volatile外,synchronized和final也能保证可见性。

有序性(Ordering)

JMM的有序性表现为:如果在本线程内观察,所有的操作都是有序的;如果在一个线程中观察另一个线程,所有的操作都是无序的。前半句指“线程内表现为串行的语义”(as-if-serial),后半句值“指令重排序”和普通变量的”工作内存与主内存同步延迟“的现象。

JMM简单了解至此,如有不同意见 指正。望不吝赐教!!!

发布了93 篇原创文章 · 获赞 1 · 访问量 3810

猜你喜欢

转载自blog.csdn.net/duan196_118/article/details/104237332