Java并发多线程与高并发(二)-并发基础
本文最后更新于:2024年4月22日 下午
在多线程的情况下,从java内存模型和CPU乱序优化浅谈多线程不安全产生的原因
序章中我们看到多线程中看到基数Demo计数出现误差,本章节从计算机原理和Java虚拟机相关探讨为什么会产生这些异常
CPU多级缓存
cpu执行频率太快,快到主存跟不上,这样在处理器处理过程中,CPU常常需要等待主存,浪费资源。所以多级缓存(cache)的出现,就是为了解决CPU和内存之间速度不匹配的问题(cpu->cache->memory)
CPU 缓存的意义
- 时间局部性(Temporal Locality):如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。
- 空间局部性(Spatial Locality):如果一个存储器的位置被引用,那么将来他附近的位置也会被引用。
CPU缓存一致性协议(MESI)
M 修改 (Modified) E 独享、互斥 (Exclusive) S 共享 (Shared) I 无效 (Invalid)
该协议目的是为了保证CPU cache之间的共享数据的一致性
更多详细信息请查阅资料
CPU多级缓存-乱序执行优化
处理器为提高运算速度而做出违背代码原有顺序的优化
cpu乱序执行的时候 可能顺序变为②->①->③
在单线程单核的情况下不会出现问题,复杂的顺序的时候多线程下可能会存在问题
Java内存模型
了解Java内存模型,了解Java内存模型如何对上述进行优化的
Java内存模型-JMM(Java Memory Model) Java内存模式是一种虚拟机规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式
cpu缓存模型结构图
Java内存模型抽象结构图
由此可见,Java 内存模型(JMM)同 CPU 缓存模型结构类似,是基于 CPU 缓存模型来建立的。
主内存、工作内存的定义
- 主内存
主内存主要存储的是 Java 实例对象,即所有线程创建的实例对象都存放在主内存中,不管该实例对象是成员变量还是方法中的本地变量(也称局部变量),当然也包括了共享的类信息、常量、静态变量。由于是共享数据区域,多条线程对同一个变量进行访问可能会发现线程安全问题。
- 工作内存(本地内存)
工作内存主要存储当前方法的所有本地变量信息(工作内存中存储着主内存中的变量副本拷贝),即每个线程只能访问自己的工作内存,即线程中的本地变量对其它线程是不可见的,就算是两个线程执行的是同一段代码,它们也会各自在自己的工作内存中创建属于当前线程的本地变量,当然也包括了字节码行号指示器、相关 Native 方法的信息。注意由于工作内存是每个线程的私有数据,线程间无法相互访问工作内存,因此存储在工作内存的数据不存在线程安全问题。