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多级缓存-乱序执行优化

处理器为提高运算速度而做出违背代码原有顺序的优化

int a=1;	//①
int b=2;	//②
int c=a+b;	//③

cpu乱序执行的时候 可能顺序变为②->①->③

在单线程单核的情况下不会出现问题,复杂的顺序的时候多线程下可能会存在问题

Java内存模型

了解Java内存模型,了解Java内存模型如何对上述进行优化的

Java内存模型-JMM(Java Memory Model) Java内存模式是一种虚拟机规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式

java-memory-model-2

cpu缓存模型结构图

6

Java内存模型抽象结构图

8

由此可见,Java 内存模型(JMM)同 CPU 缓存模型结构类似,是基于 CPU 缓存模型来建立的。

主内存、工作内存的定义

  • 主内存

主内存主要存储的是 Java 实例对象,即所有线程创建的实例对象都存放在主内存中,不管该实例对象是成员变量还是方法中的本地变量(也称局部变量),当然也包括了共享的类信息、常量、静态变量。由于是共享数据区域,多条线程对同一个变量进行访问可能会发现线程安全问题。

  • 工作内存(本地内存)

工作内存主要存储当前方法的所有本地变量信息(工作内存中存储着主内存中的变量副本拷贝),即每个线程只能访问自己的工作内存,即线程中的本地变量对其它线程是不可见的,就算是两个线程执行的是同一段代码,它们也会各自在自己的工作内存中创建属于当前线程的本地变量,当然也包括了字节码行号指示器、相关 Native 方法的信息。注意由于工作内存是每个线程的私有数据,线程间无法相互访问工作内存,因此存储在工作内存的数据不存在线程安全问题。

## 参考
[^1]: http://ifeve.com/java-memory-model-6/

Java并发多线程与高并发(二)-并发基础
https://hyq965672903.gitee.io/posts/81ef5aad.html
作者
灼华
发布于
2021年4月28日
许可协议