美文网首页
final 域的内存语义理解

final 域的内存语义理解

作者: 0爱上1 | 来源:发表于2017-12-27 14:09 被阅读139次

起点:

        在旧的java内存模型中,线程可能会看到final域的值会改变,比如,一个线程当前看到一个整型final域的值为0(还未初始化之前的默认值),过一段时间之后这个线程再去读取这个final域的值的时候,会发现值变为了1(被其他线程初始化之后的值)。常见的就是String类型的值可能会改变。

JSR-133 专家组增强了final域的语义,即通过为final域添加写和读的重排序规则,从而达到为java程序员提供初始化安全保证:只要对象是正确构造的(没有发生被构造对象的引用在构造函数中溢出),那么不需要使用同步,就可以保证任意线程都能看到这个final域在构造函数中被初始化后的值。

1:写final域规定

写final域的重排序规则:禁止把final域的写重排序到构造函数之外,实现机制是编译器会在final域的写之后,构造函数 return 之前,插入一个StoreStore屏障,这个屏障的作用就是禁止处理器把final域的写重排序到构造函数之外。

写final域的重排序规则可以确保:在对象引用为任意线程可用之前,对象的final域已经被正确初始化了,而普通域不具备这个保障,即普通域在实际构造函数中初始化时可能会被处理器重排序到构造函数之外,


这个

上图所示发生了普通域的写操作被编译器重排序到了构造函数之外,导致线程B在读取时还未完成初始化操作。

2:读final域的规定

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

读final域的重排序规则可以保证:在读一个对象的final域之前,一定会先读包含这个final域的对象的引用。即如果该引用不为null,那么引用对象的final域一定已经被初始化了。

相关文章

  • final 域的内存语义理解

    起点: 在旧的java内存模型中,线程可能会看到final域的值会改变,比如,一个线程当前看到一个整型fi...

  • final域的内存语义

    1.final域的重排序规则: 1.在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引...

  • JMM内存模型--final域的内存语义

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

  • JMM之Final

    Final相关的内存语义 final相关的两个重排序规则 在构造函数中对一个final域的引入,与随后把这个被构造...

  • 聊聊java内存模型

    本文目录 Java内存模型 重排序 内存屏障 volatitle的内存语义 final的内存语义 一、Java内存...

  • Java匿名类遇上final

    时间: 2018/10/19 Content final的普通语义 final遇见内部类 闭包 内存泄漏​ 1. ...

  • Java final内存语义

    Final final的意思是一个已初始化的变量不能再指向另外的值/对象 1.在构造函数内对final域的写入,与...

  • Java多线程(十六)---final域的内存语义

    移步java多线程系列文章 1 final域的重排序规则 1)在构造函数内对一个final域的写入,与随后把这个被...

  • volatile synchronized final的内存语

    本篇文章介绍volatile synchronized final 关键的基本概念以及的内存语义,通过自身的内存...

  • 并发编程03-Java内存模型03(final域的内存语义)

    final域的重排序规则 对于final域,编译器和处理器要遵循两个重排序规则 在构造函数内对一个final域的写...

网友评论

      本文标题:final 域的内存语义理解

      本文链接:https://www.haomeiwen.com/subject/mdtugxtx.html