java内存模型
由于CUP的速度远远高于内存的速度,所以为了加快处理,CUP自己携带一块高速缓存,在处理时,先将数据从主存中copy一份到高速缓存中,后面再刷入主存。
这种模式就导致一个问题:在多处理器下,工作缓存中和主存中数据不一致。

上图为一个简单地示例,存在变量flag,初始flag=false,线程2修改为true;当总线嗅探到后,将工作内存中的数据置为失效。
其中,涉及到的命令如下:
- read(读取):从主内存读取数据;
- load(载入):将主内存读取到的数据写入工作内存;(读取局部变量表?)
- use(使用):从工作内存读取数据来计算;(从局部变量表读取到操作数栈?)
- assign(赋值):将计算好的值重新赋值到工作内存;
- stroe(存储):将工作内存写入主内存;(简单理解为进入数据总线?)
- write(写入):将store过去的变量赋值给主存中的变量;(简单理解为从数据总线写入主存?)
- lock:将主存变量加锁,标识为线程独占状态;
- unlock:释放主存独占锁;
这些命令之间不构成原子性。
Volatile缓存
添加Volatile关键字的变量,在发生变化后,将在底层硬件级别将当前处理器缓存行的值立刻写会到系统,并触发总线嗅探机制。
可见性
- 如何处理其它线程并发修改或者stroe命令触发嗅探机制后,在当前线程write完成之前,其它线程再次的发生load加载到旧值;
解决方式:在store操作之前,当前线程会对主内存中的缓存行做互斥lock,直到write写完成,进行unlock操作。store一旦经过总线,则会触发其它CPU嗅探,失效自己处理器值,此时由于主内存中存在互斥锁,其它线程将不能进行读取与修改;
原子性
- 为何volatile不能保证原子性
原因:多处理器并发修改相同volatile变量时,若存在更新处理器缓存值后同时执行store操作,则会并发竞争主存lock锁,若线程A竞争到锁,则在A完成write写入后,会触发嗅探机制导致线程B理器缓存值失效。
两个线程若存在并发写(触发store阶段),则虽然另一个线程的工作缓存值失效,但是存在覆盖情况,这就是为啥经典的并发加时值偏小的原因。