对于final域,编译器和处理器需要遵守两个原则
- 在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序
- 初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序
写final域的重排序规则禁止把final域的写重排序到构造函数之外,写final域的重排序规则可以确保:在对象引用为任意线程可见之前,对象的final域已经被 正确初始化过了,而普通域不具有这个保障
- JMM禁止编译器把final域的写重排序到构造函数之外
- 编译器会在final域的写之后,构造函数return之前,插入一个StoreStore屏障
读final域重排序规则: 在一个线程中,初次读对象引用与初次读包含该对象的final域,这两个操作会被禁止处理器重排序. 编译器会在读final域操作前插入一个LoadLoad屏障. 读final域的重排序规则可以确保:在读一个对象的final域之前,一定会先读包含这个final 域的对象的引用
对于引用类型,写final域的重 排序规则对编译器和处理器增加了如下约束:在构造函数内对一个final引用的对象的成员域 的写入,与随后在构造函数外把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序
文章链接 https://fangzongzhou.github.io/2020/10/19/计算机/技术栈/Java/并发编程/final域/