final域的内存语义

目录

一、概述

二、final域的重排序规则

三、写final域的重排序规则

四、读final域的重排序规则

五、final域为引用类型

一、概述

        与锁和volatile相比,对final域的读和写更像是普通的变量访问。下面将介绍final域的内存语义。

        final比volatile的强度弱一些,轻量级的volatile。

二、final域的重排序规则

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

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

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

        下面通过一些示例性的代码来分别说明这两个规则:

public class FinalExample {
    int i; // 普通变量
    final int j; // final变量
    static FinalExample obj;
    public FinalExample () { // 构造函数
        i = 1; // 写普通域
        j = 2; // 写final域
    }
    public static void writer () { // 写线程A执行
        obj = new FinalExample ();
    }
    public static void reader () { // 读线程B执行
        FinalExample object = obj; // 读对象引用
        int a = object.i; // 读普通域
        int b = object.j; // 读final域
    }
}

        这里假设一个线程A执行writer()方法,随后另一个线程B执行reader()方法。通过这两个线程的交互可以说明这两个规则。

三、写final域的重排序规则

        写final域的重排序规则禁止把final域的写重排序到构造函数之外。这个规则的实现包含下面2个方面。

        1)JMM禁止编译器把final域的写重排序到构造函数之外。

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

        写final域的重排序规则可以确保:在对象引用为任意线程可见之前,对象的final域已经被正确初始化过了,而普通域不具有这个保障。

四、读final域的重排序规则

        读final域的重排序规则是,在一个线程中,初次读对象引用与初次读该对象包含的final域,JMM禁止处理器重排序这两个操作(注意,这个规则仅仅针对处理器)。编译器会在读final域操作的前面插入一个LoadLoad屏障。初次读对象引用与初次读该对象包含的final域,这两个操作之间存在间接依赖关系。由于编译器遵守间接依赖关系,因此编译器不会重排序这两个操作。大多数处理器也会遵守间接依赖,也不会重排序这两个操作。但有少数处理器允许对存在间接依赖关系的操作做重排序(比如alpha处理器),这个规则就是专门用来针对这种处理器的。

        reader()方法包含3个操作。

  •  初次读引用变量obj。
  •  初次读引用变量obj指向对象的普通域j。
  •   初次读引用变量obj指向对象的final域i。

五、final域为引用类型

        对于引用类型,写final域的重排序规则对编译器和处理器增加了如下约束:在构造函数内对一个final引用的对象的成员域的写入,与随后在构造函数外把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。

相关推荐

  1. final内存语义

    2024-02-20 01:08:02       48 阅读
  2. final, finally, finalize区别

    2024-02-20 01:08:02       49 阅读
  3. C#面:final ,finallyfinalize 区别

    2024-02-20 01:08:02       45 阅读
  4. final安全发布

    2024-02-20 01:08:02       57 阅读
  5. final

    2024-02-20 01:08:02       50 阅读
  6. 关键字:final最终

    2024-02-20 01:08:02       61 阅读
  7. ClickHouse中select final和optimize table final区别

    2024-02-20 01:08:02       75 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-20 01:08:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-20 01:08:02       106 阅读
  3. 在Django里面运行非项目文件

    2024-02-20 01:08:02       87 阅读
  4. Python语言-面向对象

    2024-02-20 01:08:02       96 阅读

热门阅读

  1. C++中max函数的使用及示例

    2024-02-20 01:08:02       54 阅读
  2. C语言:ISBN校验码

    2024-02-20 01:08:02       51 阅读
  3. Python系列(15)—— int类型转string类型

    2024-02-20 01:08:02       47 阅读
  4. Chapter 8 - 15. Congestion Management in TCP Storage Networks

    2024-02-20 01:08:02       60 阅读
  5. 如何交接一个前端项目

    2024-02-20 01:08:02       48 阅读
  6. 2024年首发!高级界面控件Kendo UI全新发布2024 Q1

    2024-02-20 01:08:02       64 阅读
  7. django rest framework 学习笔记2

    2024-02-20 01:08:02       39 阅读
  8. C++ STL 模块 —— 迭代器

    2024-02-20 01:08:02       44 阅读
  9. C++day6

    C++day6

    2024-02-20 01:08:02      55 阅读