【发布时间】:2014-06-24 23:43:13
【问题描述】:
我们知道将字段设为 final 通常是一个好主意,因为我们获得了线程安全性和不变性,这使得代码更易于推理。我很好奇是否有相关的性能成本。
Java 内存模型保证final Field Semantics:
只有在对象完全初始化后才能看到对该对象的引用的线程保证可以看到该对象的最终字段的正确初始化值。
这意味着对于这样的类
class X {
X(int a) {
this.a = a;
}
final int a;
static X instance;
}
每当线程 1 创建这样的实例时
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而是。
当 JIT 看到 final 时,它显然会避免重新排序。但它也必须强制 CPU 服从命令。是否存在相关的性能损失?
【问题讨论】:
-
所有最终字段都是自动可变的(保证可见性)
-
@Steve Visibility 得到保证,但 volatile 变量和 final 之间的性能成本完全不同。阅读期末考试不需要任何记忆障碍。
标签: java multithreading performance memory-fences