博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java内存模型
阅读量:4093 次
发布时间:2019-05-25

本文共 1921 字,大约阅读时间需要 6 分钟。

java内存模型

1.java内存模型基础

  • 内存模型 JMM
    • 线程之间通信方式主要有
      • 共享内存 java 隐式进行 内存可见性问题
      • 消息传递
    • 线程之间的共享变量存储在主内存中,每个线程对应一个私有的本地变量为共享变量的副本
      • 两个线程A B之间如果要通信那么需要以下几步
        • A线程改变本地共享变量副本更新到主内存
        • B线程读取到主内存中A线程更新的变量 本地之前的变量失效
        • 必须通过主内存
    • 指令重排序

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域两个操作不能重排序

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引用,不会从构造函数逸出
  • 参考
    • java并发编程的艺术

转载地址:http://gqiii.baihongyu.com/

你可能感兴趣的文章
自学编程的八大误区!克服它!
查看>>
GitHub 上的一个开源项目,可快速生成一款属于自己的手写字体!
查看>>
早知道这些免费 API,我就可以不用到处爬数据了!
查看>>
Java将Object类型对象转换为指定的实体类对象
查看>>
Mysql中不同字段类型对应的Java类型
查看>>
使用Gson判断两个Json字符串是否相等
查看>>
Mybatis中获取新添加记录的主键id且不受并发影响的方法
查看>>
Mybatis中useGeneratedKeys、keyProperty、keyColumn的介绍
查看>>
Java各种集合类的合并(数组、List、Set、Map)
查看>>
JS中各种数组遍历方式的性能对比
查看>>
Mysql复制表以及复制数据库
查看>>
Ant Design Vue中change等方法如何传递自定义参数
查看>>
Linux中使用nohup实现后台运行程序
查看>>
设计模式-享元模式
查看>>
DOM 对象及其元素的层级关系
查看>>
linux-命令-用户
查看>>
node启动项目报错
查看>>
数据库建模开源工具推荐——EZDML
查看>>
idea hybris integration 插件未生效
查看>>
微信测试之本地接口测试-ngrok
查看>>