Java 7
我正在阅读J. Bloch的有效Java,现在我正在关于初始化字段laziliy的部分。他引用了所谓的复核成语,如下所示:
public static void main(String[] args){
Test t = new Test();
long now = System.nanoTime();
t.getT();
long invokationTime = System.nanoTime() - now;
System.out.println(invokationTime); //Prints 3299 averagely
}
private static class Test{
private volatile Test field;
public Test getT(){
Test result = field; // <----- Note the local variable here
if(result != null){
synchronized (this) {
result = field;
if (result == null)
field = result = new Test();
}
}
return result;
}
}
他给出了使用局部变量的以下解释:
这个变量的作用是什么 确保字段 只读一次 ,这是常见的情况 已初始化。
现在,让我们考虑以下代码:
public static void main(String[] args){
Test t = new Test();
long now = System.nanoTime();
t.getT();
long invokationTime = System.nanoTime() - now;
System.out.println(invokationTime); //Prints 3101 averagely
}
private static class Test{
private volatile Test field;
public Test getT(){
if(field != null){
synchronized (this) {
if (field == null)
field = new Test();
}
}
return field;
}
}
在我的机器上,第二个lazy-init方法更快。但是在Ideone的机器上,他们大约花了7985和10630,就像J.布洛赫说的那样。那么使用这些局部变量进行优化是否值得?据我所知,读取和写入变量的成本几乎相等。
所以我们只有在方法主要由这种轻量级操作组成时才应该担心,对吗?
答案 0 :(得分:1)
这有点值得,因为您已经确定急切的加载和同步都太昂贵了。但实际上,它几乎肯定不是。您实际需要双重检查锁定代码的情况往往是非锁定数据结构和事物。高性能代码的良好设计往往会将其推向孤立的地方,因此每次触摸代码时都不会将自己射入脚中。