聊一聊final关键字

01.相关概念

    final关键字主要用来修饰类、方法和字段;当修饰类的时候,表示该类是不可继承的;当修饰方法的时候,表示该方法不可重写;当修饰字段的时候,表示该字段内容不可更改。

    相信对于Java基础比较好的以上的几点,相信大家都很熟悉了;但是在JMM中,final修饰的字段是禁止了一些重排序的

02.重排序规则

    所谓重排序,在JMM中,有3中重排序:编译级重排序规则、指令级重排序规则和内存重排序规则。JMM为了提高Java程序性能,允许一些重排序规则,但是一些重排序规则会改变程序的结果。这个时候,我们使用一些工具来禁止JMM的重排序规则,JMM将这些工具称之为内存屏障。

    内存屏障:简单的理解,就是一组CPU指令。那么JMM定义了哪些内存屏障呢?

    在上述内存屏障中,StoreLoad 屏障是一个万能屏障,几乎拥有前3种屏障的所有功能。下面我们将会分析一下final关键字的内存语义和禁止重排序规则。

03.final域内存语义

    我们先来说明针对于final关键字的两条重排序规则:

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


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

    我们来看一下下面一段代码

04.final域写内存语义

    

针对于上述代码,这里的执行过程可以是这样的

对于线程A执行的方法,主要分为两步:

  1. 就是在堆内存区域开辟空间,进行构造函数对对象初始化、   

  2. 将引用赋值给obj变量

针对于上述final域,final域的写,我们可以看到在构造函数结束之前插入了StoreStore内存屏障,JMM无法将final域的写重排序到构造函数之外。但是对于一般的变量,为了提高Java程序的性能,允许将普通变量的写重排序到构造函数之外。

针对于final域的写,这里有两条规则:

    1.JMM禁止将final域的写入重排序到构造函数之外

    2.编译器将会在final域的写入之后,return语句返回之前插入StoreStore内存屏障StoreStore内存屏障。

    在线程B中,针对于读取对象的实例数据部分,final 域的读取是初始化的值,但是对于一般变量的读取,可能读取的是初始化的旧值。

05.final域的读语义

    在上一节内容中,线程B的执行顺序是一种可能,这里我们将会看到线程B可能另一种执行的顺序,具体如下图所示:

  针对于线程B,程序员认为的操作是这样的:

    1.对去对象引用后赋值给tmp变量

    2.读取普通变量

    3.读取final变量

但是考虑到重排序问题,普通变量的读操作有可能会重排序到方法外面,显然这样的操作是不正确的;但是对于final域的读,一定是在读取final域的实例对象引用后在进行读取的。那么JMM如何实现禁止对于final域读取的重排序呢?   

     编译器会在读final域的前面插入LoadLoad内存屏障。

06.final域是引用类型

    上面分析了final域是基本类型,如果是引用类型呢,将会是什么情况呢?

这里,我们只是做一个总结:

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

    具体的情况和上述一样,留给读者去思考。

07.为什么要禁止final域的重排序呢?

    禁止final域的重排序是基于这样的考虑:如果一个线程,在读取final域的时候首先读取的final域的值是0,然后再次读取的final域值是1,这样有悖于final修饰的字段是常量的规定,所以在后来的Java规范中,增加了对final域的语义。


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容