这道题也是现实场景中热点很高的一道面试题,笔者之前也被多次问到过。无论大厂或小厂似乎都很钟意。今天我们来好好分析一下这道题,从设计意图再到原子性、可见性、有序性保证,来看看它的核心机制。
设计意图
了解背景这个非常重要,任何一个软件被设计出来都是有背景的,有意图的,为了要解决某些问题的,了解这个比它本身内部细节更重要!
Java虚拟机规范中定义了一种内存模型来屏蔽硬件与操作系统的内存访问差异,达到JAVA程序在各个平台下达到一致性的内存访问效果。
经过反复讨论后设计师们形成两个考虑点:
考虑点一:
首先对于程序员来说这个内存模型必须是严谨的(即在一个线程内的操作是有序的,或通过同步手段来保证有序);
对程序员易于理解、易于编程(单线程或正确同步的多线程程序)
考虑点二:
但又必须是宽松的,使得虚拟机的实现有足够的自由空间利用硬件的各自特性(寄存器、高速缓存、指令集中某些特有指令)来获取更好的执行速度。
需要做到尽可能减少对编译器与处理器的束缚,比如重排序
详细设计与实现
Java在命令式编程中通过共享内存的模型来实现线程间通信。
命令式编程中线程间通信有两种方式
1-共享内存
2-消息传递
所有的变量都存储在主内存中,每个工作线程都有自己的本地工作内存,线程间变量值传递必须通过主内存来完成
原子性、可见性、有序性
原子性:
我理解涉及到工作内存相关的一些列操作比如read、load、use、assign、store是原子的。但是如果对主内存的读写要保证原子性就需要用锁机制了!
可见性:
volatile通过lock指令强制刷主存,其他工作内存通过嗅探机制将自己的缓存设置为无效,重新从主内存拉取最新变量值。保证不了原子性是通过use线程1加工后最后还是要刷到主内存,和线程2一样的值刷入的!
有序性:
(Happens-before+同步工具类)