JAVA内存模式-6-final

本文详细介绍了final变量在Java中的使用规则,包括编译器和处理器如何遵循重排序规则确保final域的正确初始化,以及这些规则如何避免线程间可见性问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

final变量规则

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

  1. 在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。(编译器会在final域写之后,return之前插入一个StoreStore屏障指令)
  2. 初次读一个包含final域的对象引用,与随后初次读这个final域,这两个操作之间不能重排序。

final引用类型规则

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

为什么final引用不能从构造函数中逸出?

写final域的重排序规则可以保证:在引用变量变成任意线程可见之前,该引用变量所指向的对象的final域已经在构造函数中被正确初始化过了。

final语义在处理器中的实现

写final域重排序规则要求编译器在final域写之后、构造函数return之前,插入一个StoreStore。

读final域重排序规则要求编译器在读final域操作前面插入一个LoadLoad屏障。

final发展历史

在旧JAVA内存模型中,最严重的一个缺陷是线程可能看到final域的值会改变,例如:A线程看到一个整形final域的值为0,过一段时间之后A线程再去读final域的时候值变成了1.

为了修补这个漏洞,JSR-133增强了final语义。通过final域写、读的重排序规则,可以提供初始化安全保证:写的时候通过StoreStore强制刷新到主内存、禁止写与读重排序,这样就能保证先写后读。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值