JMM内存模型
java的内存模型中,每个线程都会有自己的工作内存,同时还会有一个共享的主内存。
工作内存:实际上是CPU的高速缓存。因为线程运行的代码对应的是一些指令,是由CPU去执行的。但是CPU每次执行指令运算的时候,也就是执行代码的时候,如果直接操作主内存里面的数据,性能会比较差。所以就有了工作内存的概念,这样线程每次执行代码的过程中,就可以直接从自己本地缓存里加载变量副本,不需要从主内存加载变量值,性能可以提升很多。
主内存:线程之间的共享变量都是存储在主内存中的。
工作内存:每个线程私有的空间区域,存储的是主内存中共享变量的副本。
线程之间的通信
线程A与线程B的通信
1、线程A把本地内存A中的共享变量副本刷新到主内存中去。
2、线程B到主内存中去读取线程A之前之前已更新过的共享变量。
JMM如何解决可见性和有序性的问题
提供happens-before原则来保证代码程序的一定可见性和有序性。
(1)程序次序规则:一个线程内,按照代码顺序,书写前面的操作先行发生于书写在后面的操作。
(2)锁定规则:一个unlock操作先行发生于后面对同一个锁的lock操作。
(3)volidate变量规则:对一个volidate变量的写操作先行发生于对这个变量的读操作。
(4)传递规则:如果操作A先行发生于操作B,操作B先行发生于操作C,则操作A先行发生于操作C。
(5)线程启动规则:一个线程的start方法先行发生于线程的每个动作。
(6)线程中断规则:对线程的interrput方法的调用先行发生于被中断线程的代码检测到终端事件的发生。
(7)线程终结规则:线程中所有的操作都先行发生线程的终止检测。
(8)对象终结规则:一个对象的初始化完成先行发生于他的finialize方法的开始。
JMM的原子性问题
JMM内存模式只保证了基本读取和赋值是原子性操作。如果要实现更大范围操作的原子性,需要通过互斥锁 synchronized
和 ReentrantLock
实现。