final域的内存语义

重排序规则

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

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

以下面实例作说明:

public class FinalExample {
    int i;
    final int j;
    static FinalExample obj;
    public FinalExapmle() {
        i = 1;
        j = 2;
    }

    public static writer() {
        obj = new FinalExample();
    }

    public static void reader() {
        FinalExample object = obj;
        int a = object.i;
        int b = object.j;
    }
}

final变量的写

 JMM禁止编译器把final域的写重排序到构造函数之外,编译器会在final域的写之后,构造函数的return之前,插入一个StoreStore内存屏障。

 

 上图显示了多线程情况下一种可能的执行顺序,final域写的重排序规则可以保证:在对象引用为任意线程可见之前,对象的final域已经被正确初始化过,而普通域不具有这个保证。

final变量的读 

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

 

final域的重排序规则可以确保:在读一个final域变量之前,一定会先读取包含这个final域的对象的引用,上例中,如果对象的引用obj不为null则final域变量一定已经初始化完成了 

Final域为引用类型 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值