【问题标题】:Been looking at lot of third party library codes lately and see this code which is confusing me最近一直在看很多第三方库代码,看到这段代码让我很困惑
【发布时间】:2018-12-25 11:22:17
【问题描述】:

这里是 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;
}

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

如果我这样写会怎样。

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

我的版本有问题吗?我在这里缺少什么?

【问题讨论】:

  • 这称为double-checked locking。尝试您首选的搜索引擎以获取更多信息。
  • 在单例初始化后,它通过避免使用同步块来提高性能。从 Java 5 开始,最好使用 volatile。见上面的链接,或者这个:cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
  • 您的版本错误,因为它允许多个线程创建新的 EventBus 实例。如果你不介意这一点,那就没有什么问题了。

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


【解决方案1】:

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

所以我们遵循双重检查初始化,它包括:

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

Source

【讨论】:

猜你喜欢
  • 2021-08-10
  • 2023-01-12
  • 2012-12-15
  • 2012-10-05
  • 1970-01-01
  • 2017-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多