java - 为什么我们不需要一个惰性初始化 getter 来同步(持有者习惯用法)?

标签 java multithreading lazy-initialization

我正在阅读 J. Bloch 的《Effective Java》,现在正在阅读有关延迟初始化的部分。考虑下面的类:

public class LazyInit{

    public static getObject(){  //Not synchronized
        return Holder.o;
    }

    private static Object createObject(){
        System.out.println("Creating started");
        return new Object();
    }

    private static class Holder{
        private static Object o = createObject();
    }
}

J.布洛赫谈到这个习语时说:

The beauty of this idiom is that the getField method is not synchronized and performs only a field access, so lazy initialization adds practically nothing to the cost of access.

我不明白为什么它可以安全通过。如果在字段初始化期间另一个线程尝试同时访问该字段怎么办?该对象在线程需要它时尚未创建。那么,会发生什么?

最佳答案

这种方法基于JVM的初始化原理。

只有在加载Holder类后才会创建Object的实例。 Holder 类的加载将由类加载器在应用程序中第一次引用字段 o 时执行(这里是 getObject 方法)。类加载是非并发的,因此此模式保证:

  1. Object 实例将根据需要创建(延迟初始化)。
  2. 对象的创建将是线程安全的。

取自 wiki article :

Since the class initialization phase is guaranteed by the JLS to be serial, i.e., non-concurrent, no further synchronization is required in the static getInstance method during loading and initialization.


评论更新:

@St.Antario 发现 formal JLS explanation对于此功能:

The procedure for initializing C is then as follows: Synchronize on the initialization lock, LC, for C. This involves waiting until the current thread can acquire LC.

关于java - 为什么我们不需要一个惰性初始化 getter 来同步(持有者习惯用法)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33773124/

相关文章:

java - Java 中的颜色检测器

ios - Swift 惰性和可选属性

java - 由于循环问题,Mapstruct 出现 LazyInitializationException

android - Pjsip 在多线程中调用它的函数时在 android 上崩溃

c++ - 线程安全的无锁内存池 : free function does not behave correctly in multi-thread

java - 尽管使用 JsonIgnore,但未能延迟初始化 ManyToMany 关系中的角色集合

java - 使用 JPA 而不是 Hibernate 设置 JBoss Seam 在 GlassFish 上运行有多容易?

JavaFX LineChart - 更改已更改位置的图例的颜色

java - 有人可以告诉我我的 JPQL 查询出了什么问题吗?抛出 The basic mapping 's.surname' Cannot be use in junction with the = 运算符错误

c sockets - 没有收到所有发送的数据