Java内存模型

Java内存模型

内存模型基础

  • 通信:线程之间以何种机制来交换消息
    • 共享内存 隐式通信
    • 消息传递 显示
  • 同步:程序中,用于控制不同线程之间的操作,发生的相同顺序的机制
    • 共享内存 显示同步
    • 消息传递 隐式同步

内存模型的抽象结构

  • 共享变量
  • 局部变量
  • image-20210620204030050

指令重排

  • 编译器优化的重排序

  • 指令级并行的重排序(数据不存在数据的依赖性)

  • 内存系统的重排序

  • as-if-serial

    不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变。编译器、runtime和处理器都必须遵循as-if-serial

image-20210620204128487

happens-before

在JMM中,人如果一个执行操作的结构需要对另一个操作可见,那么这两个操作之间必须要存在happens-before关系

  • 程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作

  • 监视器锁规则:对一个锁的解锁,happens-before于锁喉对这个锁加锁

  • volatile变量规则:多一个volatile域的写,happens-before于任意后续对这个域的读

  • 传递性:如果A happens-before B,且B happens-before C,那么A happens-before C。

  • start()规则:如果线程A执⾏操作ThreadB.start()(启动线程B),那么A线程的ThreadB.start()操作happens-before于线程B中

    的任意操作。

  • join()规则:如果线程A执⾏操作ThreadB.join()并成功返回,那么线程B中的任意操作happens-before于线程A从ThreadB.join()

    操作成功返回。

  • 线程中断规则:对线程interrupt⽅法的调⽤happens-before于被中断线程的代码检测到中断事件的发⽣。

  • 对象终结规则:⼀个对象的初始化的完成,也就是构造函数执⾏的结束⼀定 happens-before它的finalize()⽅法。

JMM设计意图

double PI = 3.14;//A
double r = 1;//B
double l = 2 * PI * r;//C
  • 程序员对内存模型的使用 为程序员提供足够强的内存可见性保证
  • 编译器和处理器对内存模型的实现 对编译器和处理器的限制要尽可能的放松

Synchronized

  • 修饰代码块

    monitorenter

    Synchronized ( this ) {

    }

  • 修饰方法

    ACC_SYNCHRONIZED

    无锁状态——偏向锁状态——轻量级锁——重量级锁

锁的内存语义

  • 线程A释放一个锁,实际上是线程A向接下来将要获取这个锁的某个线程发出了**(线程A** 对共享变量所做修改的**)**消息。
  • 线程B获取⼀个锁,实质上是线程B接收了之前某个线程发出的**(在释放这个锁之前对共 享变量所做修改的)**消息。
  • 线程A释放锁,随后线程B获取这个锁,这个过程实质上是线程A通过主内存向线程B发 送消息。

volatile的内存语义

  • 可见性
  • 原子性:赋值取值的原子性(a++不保证,这是复合操作)
  • 线程A写⼀个volatile变量,实质上是线程A向接下来将要读这个volatile 变量的某个线程发出了(其对共享变量所做修改的)消息。
  • 线程B读⼀个volatile变量,实质上是线程B接收了之前某个线程发出的(在写这个volatile变量之前对共享变量所做修改的)消息。
  • 线程A写⼀个volatile变量,随后线程B读这个volatile变量,这个过程实质上是线程A通过主内存向线程B发送消息。

内存屏障

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2QfqkY0g-1629195487271)(/Users/apple/Library/Application Support/typora-user-images/image-20210620213202411.png)]

Final的内存语义

  • 在构造函数内对⼀个final域的写⼊,与随后把这个被构造对象的引⽤赋值给⼀个引⽤变量,这两个操作之间不能重排序。
  • 初次读⼀个包含final域的对象的引⽤,与随后初次读这个final域,这两个操作之间不能重排序。
写final域重排序规则
  • JMM禁⽌编译器把final域的写重排序到构造函数之外。
  • 编译器会在final域的写之后,构造函数return之前,插⼊⼀个StoreStore屏障
读final域重排序规则
  • 在⼀个线程中,初次读对象引⽤与初次读该对象包含的final 域,JMM禁⽌处理器重排序这两个操作

多线程下的单例模式

  • 双重检查锁定
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值