java - 为什么在 Joshua Bloch Effective Java Example 中双重检查锁定快 25%

标签 java multithreading volatile

下面是 Effective Java 第二版的一个片段。作者声称以下代码比不使用 result 变量的代码快 25%。 根据这本书“这个变量的作用是确保该字段在已经初始化的常见情况下只被读取一次。” . 我无法理解为什么与不使用局部变量 result 相比,初始化值后这段代码会更快。在任何一种情况下,无论您是否使用局部变量 result,您在初始化后都将只有一次 volatile 读取。

// 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;
}

最佳答案

一旦 field 被初始化,代码是:

if (field == null) {...}
return field;

或:

result = field;
if (result == null) {...}
return result;

在第一种情况下,您读取了 volatile 变量两次,而在第二种情况下,您只读取了一次。虽然 volatile 读取非常快,但它们可能比从局部变量读取慢一点(我不知道是不是 25%)。

注意事项:

  • volatile 读取与最近的处理器(至少 x86)/JVM 上的正常读取一样便宜,即没有区别。
  • 然而,编译器可以更好地优化没有 volatile 的代码,因此您可以从更好的编译代码中获得效率。
  • 无论如何,25% 的几纳秒仍然不算多。
  • 这是一个标准习语,您可以在 java.util.concurrent 包的许多类中找​​到它 - 例如参见 this method in ThreadPoolExecutor (有很多)

关于java - 为什么在 Joshua Bloch Effective Java Example 中双重检查锁定快 25%,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17164454/

相关文章:

java - SimpleDateFormat 和 android.text.format.DateFormat 有什么区别?

java - 从 JAX-WS 异步 Web 服务获取 HTTP 响应代码

python - 如何从 Cython 中的另一个线程设置 future\add 到队列的结果?

c# - 内存障碍和大型结构?

c++ - 对一段代码进行计时时是否需要 volatile?

java - CPU 单核 : Need volatile or synchronized?

java - "VerifyError: Expecting to find object/array on stack"在Java中使用ASM监控对象创建时?

java - 将Java类转换为C程序

python - 如何向 Qthread 发送参数

java - 我可以在 Singleton Enterprise Java Bean 中启动 ManagedThread 吗?