Java内存模型简析

CPU多级缓存

CPU的存储速度远远高于内存的访问速度,为了匹配CPU的高速度加入了一级缓存,但是由于高速缓存很贵容量比较小,后来又增加了容量稍大的二级缓存。缓存的存在理论主要依靠程序的时间和空间局部性原理提供支持:

  • 时间局部性:如果某个数据被访问,那么在不久的将来它很可能再次被访问。
  • 空间局部性:如果某个数据被访问,那么与它相邻的数据很快也会被访问。

CPU多级缓存的缓存一致性:MESI协议,用于保存多个CPU缓存之间缓存共享数据的一致性。

Modify表示被修改,Exclude表示独享,Share表示被多个CPU共享,Invalid缓存行是无效的,可能是其他CPU修改了这个缓存数据。引起状态转换分为Local Read也就是本地缓存读,Local Write本地缓存写,Remote Read读取主内存,Remote Write向主内存中写入。

主内存和工作内存

Java内存模型的主要目的是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节,由于处在栈中的局部变量和方法参数都不会被共享,因而JMM主要描述多线程环境中共享变量与内存的关系。
这里写图片描述
JMM中规定所有的变量都保存在主内存中,不同的线程都有自己的工作内存,工作内存对应着前面提到的CPU缓存,所有线程在使用主内存中的变量必须先将变量拷贝到工作内存中,线程只能处理工作内存中拷贝,不同的线程无法访问别的线程的工作内存,如果希望将自己修改的变量通知到别的线程必须通过主内存来完成。

重排序问题

Java中的多线程是并发执行的,为了能够提升执行的效率,Java编译器和CPU内部都会对指令排列做优化操作,除此之外CPU内部的各种读写缓存也会导致内存读写重排序。优化后的代码在单线程中执行能够保证执行结果和未优化的代码保持一致,不过当多个线程之间存在了变量读写的隐式依赖关系,优化后重排序指令无法保证和未优化代码逻辑一致,为了避免重排序导致的逻辑问题,JVM提供了内存屏障指令,这些指令可以告知编译器和CPU屏障前后的某些指令禁止重排序。

Java内存模型围绕着并发过程中如何处理原子性、可见性和有序性这三个特征来建立的:

  • 原子性:操作要么全部都执行完,要么都不执行
  • 可见性:一个线程对主内存的修改可以及时的被其他线程观察到
  • 有序性:在本线程内观察,所有的操作都是有序的;在一个线程中观察另外一个线程,所有的操作都是无序的

volatile是一种轻量级的同步机制,能够保证变量的可见性和有序性,无法保证原子性。volatile保证变量在一个线程中被修改,新的值对之后其他的线程都是可见的,volatile保证在写入变量的时候会将工作内存中的变量全部同步到主内存中,volatile读操作会将工作内存中变量的拷贝清空并且重新从主内存中加载变量新值。volatile还能禁止指令重排序工作,这样从其他线程观察volatile变量执行的指令就是有序的。

synchronized加锁操作具有和volatile读操作一样会将工作内存中的拷贝清空重新从主内存中读取,synchronized解锁操作具有和volatile写一样会将工作内存中的变量同步到主内中,而且锁对象被线程获取之后不会被其他线程获取,这就保证了操作的原子性,同时由于锁保护的临界区代码只有一个线程能够执行就保证了代码执行的有序性。

final在修饰类的实例成员变量的时候,如果在构造函数执行完成之前this没有逸出,那么在其他线程中就能够看到final类型字段,这也是一种保证内存可见性的方法。

happens-before关系

Java中如果不使用前面的volatile、synchronized和final关键字来实现有序性,可以依靠Java语言中的happens-before关系来确定操作的有序性,这种规则是是由Java语言内部支持实现的。在JMM中一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须存在happens-before关系:

  • 单线程执行顺序具有先后性
  • unlock发生在lock之前
  • volatile写先行于后面对这个变量的读volatile读
  • 线程中所有操作发生在start之后,同时发生在join之前
  • 线程interrupt方法先行于中断事件被代码检测到
  • 构造函数发生在finalizer开始之前
  • 具有传递性

Java中无需任何同步手段就能保证上面的先行规则,如果两个操作之间无法通过happens-before关系推导出来,JVM就不会保证它们执行的顺序性。

扫描二维码关注公众号,回复: 2250661 查看本文章

猜你喜欢

转载自blog.csdn.net/xingzhong128/article/details/80604837