java - 为什么在 Java 中双重检查锁定被破坏?

标签 java multithreading synchronization locking anti-patterns

这个问题与旧 Java 版本的行为和双重检查锁定算法的旧实现有关

较新的实现 use volatile并依赖于略微改变的 volatile 语义,因此它们不会损坏。


声明字段分配始终是原子的,除了 long 或 double 字段。

但是,当我读到为什么 double-check locking 被破坏的解释时,它说问题出在赋值操作中:

// Broken multithreaded version
// "Double-Checked Locking" idiom
class Foo {
    private Helper helper = null;
    public Helper getHelper() {
        if (helper == null) {
            synchronized(this) {
                if (helper == null) {
                    helper = new Helper();
                }
            }
        }
        return helper;
    }

    // other functions and members...
}
  1. Thread A notices that the value is not initialized, so it obtains the lock and begins to initialize the value.
  2. Due to the semantics of some programming languages, the code generated by the compiler is allowed to update the shared variable to point to a partially constructed object before A has finished performing the initialization.
  3. Thread B notices that the shared variable has been initialized (or so it appears), and returns its value. Because thread B believes the value is already initialized, it does not acquire the lock. If B uses the object before all of the initialization done by A is seen by B (either because A has not finished initializing it or because some of the initialized values in the object have not yet percolated to the memory B uses (cache coherence)), the program will likely crash.
    (from http://en.wikipedia.org/wiki/Double-checked_locking).

什么时候可以? 64 位 JVM 赋值操作是否可能不是原子的? 如果不是那么“双重检查锁定”是否真的被破坏了?

最佳答案

问题不在于原子性,而在于顺序。允许 JVM 重新排序指令以提高性能,只要 happens-before没有被侵犯。因此,运行时理论上可以在类 Helper 的构造函数执行完所有指令之前安排更新 helper 的指令。

关于java - 为什么在 Java 中双重检查锁定被破坏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4926681/

相关文章:

java - Spring Boot中如何使用阻塞队列?

java - 信号量和 Java 计数

c++ - pthread 多线程

java - Eclipse 中的 list 文件

java - 为什么在预热阶段浮点运算要快得多?

java - 如何在Java中动态改变对象的泛型类型?

java - 在Java中计算附加值

windows - Windows 中信号量的发布顺序是什么?

windows - Windows Server 2003 中的最大线程数是多少?

c++ - 获取优先于提升进程的互斥量