最近一直在查看许多第三方图书馆代码,并看到使我感到困惑的代码

时间:2018-12-25 11:22:18

标签: java android greenrobot-eventbus greenrobot-eventbus-3.0

这是EventBus getDefault()静态方法的一部分代码,该方法返回EventBus类的静态实例。

/** Convenience singleton for apps using a process-wide EventBus instance. */
public static EventBus getDefault() {
    EventBus instance = defaultInstance;
    if (instance == null) {
        synchronized (EventBus.class) {
            instance = EventBus.defaultInstance;
            if (instance == null) {
                instance = EventBus.defaultInstance = new EventBus();
            }
        }
    }
    return instance;
}

我看到代码首先检查instance是否为null,然后在synced块中再次进行相同的检查。为什么会这样。

如果我这样写怎么办?

/** Convenience singleton for apps using a process-wide EventBus instance. */
public static EventBus getDefault() {
    EventBus instance = defaultInstance;
    if (instance == null) {
        synchronized (EventBus.class) {
            instance = EventBus.defaultInstance = new EventBus();
        }
    }
    return instance;
}

我的版本有问题吗?我在这里想念什么?

1 个答案:

答案 0 :(得分:1)

在您的代码中,当instance为null时,两个线程可以同时进入if语句内部。然后,一个线程进入同步块以初始化实例,而另一个则被阻塞。当第一个线程退出同步块时,等待线程进入并创建另一个Singleton对象。请注意,当第二个线程进入同步块时,它不会检查实例是否为非空。

因此,我们遵循双重检查初始化,其中包括:

  1. 检查变量是否已初始化(未获取锁)。如果已初始化,请立即返回。
  2. 获取锁。
  3. 仔细检查变量是否已经初始化:如果另一个线程首先获取了锁,则它可能已经完成了初始化。如果是这样,则返回初始化变量。
  4. 否则,初始化并返回变量。

Source