一、JMM内存管理
1.1 作用
它描述了一系列的规则或者规范,用来解决多线程的共享变量问题
1.2 结构
- 主存储器
- 工作内存
结构图
1.3 特点
-
有序性
除了多线程这种无序性观测,无序的产生还来源于指令重排 -
可见性
线程修改了共享变量的值,其他线程也能立刻感知到这种变化
方式:volatile 、synchronized 、final 和锁 -
原子性
颗粒度更大的原子性保证,可以使用lock 、unlock 这两个操作
1.4 内存屏障
- 内存屏障(Memory Barrier)用于控制特定条件下的重排序和内存可见性问题
- 内存屏障可分为读屏障和写屏障
- Java的内存屏障实际上也是上述两种的组合,完成一系列的屏障和数据的同步功能
- Java编译器在生成字节码时,会在执行指令序列的适当位置插入内存屏障来闲置处理器的重排序。
二、并发编程的问题
2.1 三大问题
关于并发编程的问题有所了解,比如原子性问题,可见性问题和有序性问题。
其实,原子性问题,可见性问题和有序性问题。是人们抽象定义出来的。而这个抽象的底层问题就是前面提到的缓存一致性问题、处理器优化问题和指令重排问题等。
- 原子性是指在一个操作中就是cpu不可以在中途暂停然后再调度,既不被中断操作,要不执行完成,要不就不执行。
- 可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
- 有序性即程序执行的顺序按照代码的先后顺序执行。
缓存一致性问题其实就是可见性问题。而处理器优化是可以导致原子性问题的。指令重排即会导致有序性问题
2.2 Java内存模型抽象
从抽象角度来看,JMM 定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,本地内存中存储了该线程以读 / 写共享变量的副本。本地内存是 JMM 的一个抽象概念,并不真实存在
线程的通信步骤
- 线程 A 把本地内存 A 中更新过的共享变量刷新到主内存中去
- 线程 B 到主内存中去读取线程 A 之前已更新过的共享变量