一、简介
- JMM((Java Memory Model)是Java内存模型,与JVM内存模型不同,与CPU内存模型相似
- 它定义了程序中各个共享变量的访问规则
- 它屏蔽了各种硬件和操作系统的内存访问差异,使Java程序在各种平台下都能达到一致的内存访问效果
如上图所示,每个线程拥有自己的工作内存(类比于高速缓存),工作内存中保存的是主内存中变量的副本,线程对变量的读写操作是在自己的工作内存中进行,而不是直接读写主内存中的变量。
由于每个线程都有一个共享变量副本,因此在多线程环境下,就会出现问题。
二、三大性质
并发编程时,保证线程安全,需要关注这三条性质:原子性、可见性、有序性。
1、原子性
- 一个操作是原子操作那么我们称它具有原子性
- 对于原子操作,要么发生,要么完全不发生,不存在中间状态
- JMM保证除long、double外的基本数据类型的读写操作是原子操作
- 使用synchronized也可以提供原子操作
2、可见性
- 一个线程对共享变量的修改,另一个线程能够立刻看到
- volatile强制变量的赋值会同步刷新回主内存中,强制变量的读取从主内存中加载
3、有序性
- java为了优化代码。可能会对指令重排
- 有序性保证程序执行的顺序按照代码的先后顺序执行
- volatile可以保证有序性
三、其他
1、JMM八大原子操作
名称 | 功能 |
---|---|
read(读取) | 从主内存中读取数据 |
load(载入) | 将主内存读取到的数据存储到工作内存 |
use(使用) | 把工作内存中的值传递给执行引擎 |
assign(赋值) | 把执行引擎获取的值赋值给工作内存 |
store(存储) | 将工作内存数据写入主内存 |
write(写入) | 将store到主内存的数据赋值给主内存的变量 |
lock(锁定) | 将主内存变量加锁,标识为线程独占状态 |
unlock(解锁) | 将主内存变量解锁,解锁以后其它线程就可以锁定该变量 |
2、总线嗅探机制
- CPU将主内存中的数据读取到线程工作内存中,读取操作是通过计算机中的BUS总线进行的;
- BUS总线存在总线嗅探机制,某个共享变量被volatile修饰后,一旦在某个线程中修改了该变量的值,就会向BUS总线发送共享变量改变的消息;
- CPU收到该消息,就会将其他线程工作内存中的共享变量置为失效状态。
- 通过总线嗅探机制保证可见性
3、内存屏障
- 为了性能编译器和处理器会对指令进行重排序
- 内存屏障是一条指令,该指令可以对编译器(软件)和处理器(硬件)的指令重排做出一定的限制
- 通过内存屏障保证有序性
网友评论