赞
踩
纯属学习B站教学视频笔记,方便查阅
CPU高速(对应电脑上)缓存:现代CPU性能强运算速度快,而RAM速度并没有随之增长,所以如果CPU直接和RAM通信会直接拉低了CPU性能。运行程序时,把主内存RAM数据读取到CPU高速缓存,通过高速缓存和CPU进行数据交互。不过高速缓存就稍微有点贵。
Java线程内存模型和Cpu缓存模型类型,是基于Cpu缓存模型来建立的,Java线程内存模型是标准化的,屏蔽掉了底层不同计算机的区别。主要注意每个线程自己独立拥有的
工作内存
以及共享变量副本
。
举个错误例子:
public class VolatileVisibilityTest {
// private static volatile boolean initFlag = false; // 注意volatile可见性
private static boolean initFlag = false;
public static void main(String[] args) throws InterruptedException{
new Thread(()->{
System.out.println("waiting data...");
while(!initFlag) {
}
System.out.println("============ success");
}).start();
Thread.sleep(2000);
new Thread(()->prepareData()).start();
}
public static void prepareData() {
System.out.println("prepareData data...");
initFlag = true;
System.out.println("prepareData data end...");
}
}
通过JMM原子操作理解Java内存模型。
以原子操作解读上面的代码。先解读没有加Volatile的代码
到这一步其实就可以看到,数据不一致(数据修改可见性)。
多个cpu从主内存读取同一个数据到各自的高速缓存,当其中某个cpu修改了缓存里的数据,该数据会马上同步回主内存,其他cpu通过
总线嗅探
机制可以感知到数据的变化从而将自己缓存里的数据失效
。
在上面的基础上,
重新read store之后会得到新的值。
底层实现主要是通过汇编lock前缀指令,它会锁住这块内存区域的缓存(缓存行锁定)并回写到主内存。
注意一下加锁位置(加锁颗粒度考虑问题
):
private static volatile int num = 0;
多线程执行一个 num++
多个线程同一时刻做num++
要解决这个原子性问题,最终还是得在线程进行操作数据的时候做一些加锁限制。(也就是对方法加锁)
synchronized
关键字- Java.util.concurrent包中的
lock
接口和ReentrantLock
实现类
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。