java内存模型
1.java内存模型基础
- 内存模型 JMM
- 线程之间通信方式主要有
- 共享内存 java 隐式进行 内存可见性问题
- 消息传递
- 线程之间的共享变量存储在主内存中,每个线程对应一个私有的本地变量为共享变量的副本
- 两个线程A B之间如果要通信那么需要以下几步
- A线程改变本地共享变量副本更新到主内存
- B线程读取到主内存中A线程更新的变量 本地之前的变量失效
- 必须通过主内存
- 两个线程A B之间如果要通信那么需要以下几步
- 指令重排序
- 线程之间通信方式主要有
2.重排序
- 编译器和处理器为了提高性能,通常会对指令进行重排序
- 编译器优化的重排序
- 指令级并行的重排序
- 内存系统的重排序
- 数据依赖性
- 写后读
- 写后写
- 读后写
- 仅针对单个处理器或单线程程序
- as-if-serial
- 不管如何重排序 不影响程序的最终结果
- 处理器和编译器不会对存在数据依赖的操作进行重排序
3.顺序一致性
- 理论参考模型
- 数据竞争
- 两个线程对同一个变量进行读写且写读没有通过同步来排序
- 一个线程的操作必须按照程序的顺序来执行
- 每个操作必须原子性和立刻对所有线程可见
- 允许把一个64位的double和long类型的写操作拆分成两个32位操作来执行,任意读操作必须具有原子性。
4.volatile
- volatile
- 一个volatile变量的读写操作与一个普通变量的读写加锁来同步的执行效果相同
- happens-before(后面会讲)保证锁的释放与获取过程的两个线程之间的内存可见性,那么对于volatile变量的读操作总是能看见任意线程对该变量最后的写入。
- 特性
- 原子性
- 可见性 对任意单个volatile变量的读写具有原子性但v++不具有
- 特性
- 对volatile的读-写操作可以实现线程之间的通信;与锁的释放获取具有相同的内存效果
- 写的内存语义
- JMM会把该线程对应的本地变量刷新到主内存中
- 读的内存语义
- JMM会把线程本地内存置为无效,然后从主内存中读取共享变量
- 小结
- A线程写了一个volatile变量,实质是A线程向接下去要读取该变量的线程发出修改的消息
- B线程读取volatile变量实质上是接收某个线程发出的对此变量做出修改的消息
- A写 B读实质上通过主内存进行通信
- volatile重排序规则
- 当第二个操作为volatile写 不管第一个操作是什么都不能重排序
- 当第一个操作为volatile读 不管第二个操作是什么都不能重排序
- 当第一个是volatile写 第二个是volatile读 不能重排序
- 锁释放与获取内存语义
- 释放 同 volatile写
- 获取 同 volatile读
5.final
- 两个重排序规则
- 在构造函数内对final域的写入,与随后把这个构造对象的引用赋值给另一个引用变量两个操作不能重排序
- JMM禁止把final域的写重排序到构造函数外
- 编译器 写之后return之前 插入StroeStroe屏障
- 初次读final域对象的引用与随后初次读这个final域两个操作不能重排序
- 在构造函数内对final域的写入,与随后把这个构造对象的引用赋值给另一个引用变量两个操作不能重排序
6.happens-before
- 核心概念
- 便于理解,易于编程
- 编译器希望束缚较少,尽可能挺高性能
- 策略
- 对于会改变程序结果的重排序,要求必须禁止
- 对于不影响的 不做要求
- 一个线程的执行结果需要对另一个操作可见
- 定义
- 一个操作 hb 与另一个操作 那么第一个的结果对于第二个可见且执行顺序1>2
- 两个操作存在hb 关系重排序执行结果不一致 不合法
- as-if-serial 针对单线程,happens-before针对多线程
- 规则
- 程序顺序规则
- 一个线程的每个操作hb于该线程的任意后续操作
- 监视器锁规则
- 对一个锁的解锁hb于随后对该锁的加锁
- volatile变量规则
- 写 hb于 读
- 传递性
- A happens-before B
- B happens-before C
- A happens-before C
- start()规则
- A线程执行B.start 那么 B.start() hb于任意B线程的操作
- join() 规则
- A执行B.join()成功并返回B中任意操作hb于之前的操作返回成功
- 程序顺序规则
- 双重检查锁定与延迟初始化
- 基于volatile
- 基于类初始化
- 延伸至 单例设计模式
7.小结
- 处理器内存模型
- 顺序一致性模型是参考 JMM和处理器内存模型依照做一些优化
- JMM屏蔽了各个处理器内存模型之间的差异
- 各个模型之间的关系
- JMM属于语言级模型
- 处理器模型属于硬件级内存模型
- 顺序一致性内存模型理论参考模型
- 对旧模型的修补
- 增强volatile
- 限制volatile与普通变量的重排序,使得与锁的释放获取具有相同内存语义
- 增强final
- 增加两个重排序
- 保证final引用,不会从构造函数逸出
- 增强volatile
- 参考
- java并发编程的艺术