并发编程之:Java内存模型

并发编程之:Java内存模型

介绍

Java内存模型在分析并发问题时是非常重要的。

硬件处理模型

绝大多数的运算任务都不可能只靠处理器就能完成,处理器至少要与内存交互,比如读取数据、存储运算结果等。 
这个I/O操作是很难消除的(无法仅靠寄存器来完成所有的运算任务)。

由于计算机存储设备与处理器的运算速度存在几个数量级的差距,所以现代计算机系统都不得不一层高速缓存作为内存和处理器之间的缓冲。 

将运算需要使用到的数据复制到缓存中,让运算能快速进行,当运算结束后再从缓存中同步到内存中,这样处理器就无序等待缓慢的内存读写了。

高速缓存的存储交互很好的解决了吹起和内存的速度矛盾,但是也为计算机系统带了了更高的复杂度,因为它引入了一个新的问题:缓存一致性。

在多处理器系统中,每个处理器都有自己告诉缓存,而它们又共享同一主存。

因此当多个处理器运算任务都涉及到同一块主内存区域时,将可能导致各自的缓存数据不一致。 
因此不同的物理计算机系统,访问缓存时都会遵循一些协议。不同的系统可能遵循的是不同的协议,而JVM则做到了兼容。
除了增加高速缓存之外,为了使得处理器内部的运算单元能尽量被充分利用,处理器可能会对代码进行乱序执行优化。

与处理器的乱序执行优化类似,Java虚拟机的即时编译器也有类似的指令重排序优化。

处理器、缓存、主存之间交互关系

《并发编程之:Java内存模型》

Java内存模型

Java虚拟机规范中定义了一种Java内存模型,来屏蔽掉各种硬件和操作系统的内存访问差异,以实现Java程序在不同平台下都能达到一致内存访问效果。

主内存和工作内存

Java内存模型规定了所有的变量都存储在主内存中(此主内存和物理硬件的住内存类似,可以类比理解,但是此处是虚拟机内存的一部分)。

每个线程还有自己的工作内存(可以与物理硬件中的告诉缓存类比),线程中的工作内存保存了该线程使用到变量的主内存的副本拷贝, 
线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。

不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量的传递需要通过主内存完成。

线程、主内存、工作内存交互关系

《并发编程之:Java内存模型》

内存间相互操作

Java内存模型中定义了以下八种操作来完成,虚拟机实现时必须保证下面提及的每一种操作都是原子的、不可再分的。

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

unlock(解锁):作用于主内存的变量,它把一个出于锁定状态的变量释放出来

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

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

assign(赋值):作用于主内存的变量,它把工作内存中的一个变量的值传递给执行引擎,它把一个从执行引擎接收到的值赋给工作内存的变量, 
每当虚拟机遇到一个给变量赋值的字节码指令时就执行这个操作 

store(存储):作用于主内存的变量,它把工作内存中的一个变量的值传递给执行引擎,它把一个从执行引擎接收到的值赋给工作内存的变量,
它把工作内存中一个变量的值传送到主内存中,以便随后的write操作使用 

write(写入):作用于主内存的变量,它把工作内存中的一个变量的值传递给执行引擎,它把一个从执行引擎接收到的值赋给工作内存的变量, 
它把store操作从工作内存中得到的变量的值放入主内存的变量中

对于volatile型变量的特殊规则

详细请参考volatile关键字博客

参考

1、《深入理解Java虚拟机》

    原文作者:java内存模型
    原文地址: https://blog.csdn.net/nicewuranran/article/details/52304049
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞