【Java学习笔记(一百二十九)】之 final域重排序规则,JMM内存可见性保证

本文章由公号【开发小鸽】发布!欢迎关注!!!


老规矩–妹妹镇楼:

一. final域

(一) 重排序规则

        对于final域,编译器和处理器要遵守两个重排序规则:

        1. 在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。

        2. 初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序。

(二) 写final域的重排序规则

        写final域的重排序规则禁止把final域的写重排序到构造函数之外,同时编译器在final域的写之后,构造函数return之前,插入一个StoreStore屏障,这个屏障禁止处理器把final域写重排序到构造函数之外。

(三) 读final域的重排序规则

        在一个线程中,初次读对象引用与初次读该对象包含的final域,JMM禁止处理器重排序这两个操作,编译器会在读final域操作前面插入一个LoadLoad屏障,确保读final域之前该对象已经初始化。

(四) final引用不能逸出构造函数

        写final域的重排序规则可以保证,在引用变量为任意线程可见之前,该引用变量指向的对象的final域已经在构造函数中被正确初始化了。要得到这种效果,还需要保证在构造函数内部,不能让这个被构造对象的引用被其他线程所见。

(五) JSR-133增强final语义的意义

        通过为final域增加写和读重排序规则,可以为Java程序员提供初始化安全保证,只要对象是正确构造的,那么不需要同步就可以保证任意线程都能看到这个final域在构造函数中被初始化之后的值 。

二. happens-before

        JSR-133使用happens-before来指定两个操作之间的执行顺序,由于这两个操作可以在一个线程之内,也可以在不同线程之间,因此,JMM通过happens-before关系向程序员提供跨线程的内存可见性保障,即确保正确同步的多线程程序的执行结果不被改变。

三. JMM的内存可见性保证

        Java的内存可见性保证分为三类:

(一) 单线程程序

        不会出现内存可见性问题,因为编译器和处理器会确保单线程程序执行结果和顺序一致性模型中的执行结果一致,通过重排序规则来禁止有依赖关系的重排序优化。

(二) 正确同步的多线程程序

        将具有顺序一致性,JMM通过限制编译器和处理器的重排序来提供内存可见性保证。

(三) 未正确同步的多线程程序

        JMM提供了最小安全性保障,线程执行时读取到的值,要么是之前某个线程写入的值,要么是默认值(0,null,false)。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值