为什么在Joshua Bloch Effective Java示例中,双重检查锁定的速度提高了25%

ver*_*tas 9 java multithreading volatile java-ee

嗨,下面是Effective Java 2nd Edition的片段.在这里,作者声称下面的代码比你不使用结果变量快25%.根据书中的"这个变量的作用是确保该字段在已经初始化的常见情况下只读取一次." .我无法理解为什么这个代码在初始化之后会比较快,如果我们不使用Local变量结果.在任何一种情况下,无论是否使用局部变量结果,初始化后只有一个易失性读取.

// Double-check idiom for lazy initialization of instance fields 
private volatile FieldType field;

FieldType getField() {
    FieldType result = field;
    if (result == null) {  // First check (no locking)
        synchronized(this) {
            result = field;
            if (result == null)  // Second check (with locking)
                field = result = computeFieldValue();
        }
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

ass*_*ias 10

Once field has been initialised, the code is either:

if (field == null) {...}
return field;
Run Code Online (Sandbox Code Playgroud)

or:

result = field;
if (result == null) {...}
return result;
Run Code Online (Sandbox Code Playgroud)

In the first case you read the volatile variable twice whereas in the second you only read it once. Although volatile reads are very fast, they can be a little slower than reading from a local variable (I don't know if it is 25%).

Notes:

  • volatile reads are as cheap as normal reads on recent processors (at least x86)/JVMs, i.e. there is no difference.
  • however the compiler can better optimise a code without volatile so you could get efficiency from better compiled code.
  • 25% of a few nanoseconds is still not much anyway.
  • 它是java.util.concurrent包的许多类中可以找到的标准习惯用法 - 请参阅ThreadPoolExecutor中的此方法(其中有很多)