Java内存模型(Java Memory Model)简称J M M,作为Java并发编程系列的开篇,它是Java并发编程的基础知识,理解它能让你更好的明白线程安全到底是怎么一回事。
内容大纲
硬件内存模型
程序是指令与数据的集合,计算机执行程序时,是C P U在执行每条指令,因为C P U要从内存读指令,又要根据指令指示去内存读写数据做运算,所以执行指令就免不了与内存打交道,早期内存读写速度与C P U处理速度差距不大,倒没什么问题。
C P U缓存
随着C P U技术快速发展,C P U的速度越来越快,内存却没有太大的变化,导致内存的读写(IO)速度与C P U的处理速度差距越来越大,为了解决这个问题,引入了缓存(Cache)的设计,在C P U与内存之间加上缓存层,这里的缓存层就是指C P U内的寄存器与高速缓存(L1,L2,L3)
从上图中可以看出,寄存器最快,主内最慢,越快的存储空间越小,离C P U越近,相反存储空间越大速度越慢,离C P U越远。
C P U如何与内存交互
C P U运行时,会将指令与数据从主存复制到缓存层,后续的读写与运算都是基于缓存层的指令与数据,运算结束后,再将结果从缓存层写回主存。
上图可以看出,C P U基本都是在和缓存层打交道,采用缓存设计弥补主存与C P U处理速度的差距,这种设计不仅仅体现在硬件层面,在日常开发中,那些并发量高的业务场景都能看到,但是凡事都有利弊,缓存虽然加快了速度,同样也带来了在多线程场景存在的缓存一致性问题,关于缓存一致性问题后面会说,这里大家留个印象。
Java内存模型
Java内存模型(Java Memory Model,J M M),后续都以J M M简称,J M M 是建立在硬件内存模型基础上的抽象模型,并不是物理上的内存划分,简单说,为了使Java虚拟机(Java Virtual Machine,J V M)在各平台下达到一致的内存交互效果,需要屏蔽下游不同硬件模型的交互差异,统一规范,为上游提供统一的使用接口。
J M M是保证J V M在各平台下对计算机内存的交互都能保证效果一致的机制及规范。
抽象结构
J M M抽象结构划分为线程本地缓存与主存,每个线程均有自己的本地缓存,本地缓存是线程私有的,主存则是计算机内存,它是共享的。
不难发现J M M与硬件内存模型差别不大,可以简单的把线程类比成Core核心,线程本地缓存类比成缓存层,如下图所示
Java中提供了synchronized(同时满足有序性、原子性、可见性)可以保证结果的原子性(注意这里的描述),synchronized保证原子性的原理很简单,因为synchronized可以对代码片段上锁,防止多个线程并发执行同一段代码(本文重点是J M M,所以不会对synchronized做过多的解读)。