使用最终字段的成本 [英] Cost of using final fields

查看:89
本文介绍了使用最终字段的成本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们知道,使字段为final通常是一个好主意,因为我们获得了线程安全性和不变性,这使代码更易于推理.我很好奇是否存在相关的性能成本.

We know that making fields final is usually a good idea as we gain thread-safety and immutability which makes the code easier to reason about. I'm curious if there's an associated performance cost.

Java内存模型可保证 final Field Semantics :

The Java Memory Model guarantees this final Field Semantics:

一个线程只能在完全初始化该对象之后才能看到对该对象的引用,这保证了该对象的最终字段可以看到正确初始化的值.

A thread that can only see a reference to an object after that object has been completely initialized is guaranteed to see the correctly initialized values for that object's final fields.

这意味着对于这样的课程

This means that for a class like this

class X {
    X(int a) {
        this.a = a;
    }
    final int a;

    static X instance;
}   

只要线程1创建了这样的实例

whenever Thread 1 creates an instance like this

X.instance = new X(43);
while (true) doSomethingEventuallyEvictingCache();

并且线程2看到了

 while (X.instance == null) {
      doSomethingEventuallyEvictingCache();
 }
 System.out.println(X.instance.a);

它必须打印43.如果不使用final修饰符,则JIT或CPU可以对存储重新排序(先存储X.instance然后设置a=43),线程2可以看到默认的初始化值并打印0代替.

it must print 43. Without the final modifier, the JIT or the CPU could reorder the stores (first store X.instance and then set a=43) and Thread 2 could see the default-initialized value and print 0 instead.

当JIT看到final时,显然可以避免重新排序.但这还必须迫使CPU遵守命令.有相关的性能损失吗?

When JIT sees final it obviously refrains from reordering. But it also has to force the CPU to obey the order. Is there an associated performance penalty?

推荐答案

是否有相关的性能损失?

Is there an associated performance penalty?

如果您查看JIT编译器的源代码,则会在文件

If you take a look at the source code of the JIT compiler, you will find the following comment regarding final member variables in the file src/share/vm/opto/parse1.cpp:

此方法(必须是Java规则的构造函数)写了一个final.在构造函数将对新构造函数对象的引用发布到任何代码之前,必须将所有初始化的效果提交给内存.无需等待发布,我们只需在此处阻止写入即可.我们不会仅对需要完成的那些写入操作设置障碍,而是强制所有写入完成.

This method (which must be a constructor by the rules of Java) wrote a final. The effects of all initializations must be committed to memory before any code after the constructor publishes the reference to the newly constructor object. Rather than wait for the publication, we simply block the writes here. Rather than put a barrier on only those writes which are required to complete, we force all writes to complete.

如果存在最终成员变量,则编译器将发出其他指令.这些附加说明很可能会导致性能下降.但是目前尚不清楚这种影响是否对任何应用程序都重要.

The compiler emits additional instructions if there are final member variables. Most likely, these additional instructions cause a performance penalty. But it's unclear, if this impact is significant for any application.

这篇关于使用最终字段的成本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆