7

我有一个多线程应用程序和一个单例类:

public final class Singleton {

    private static MyClass mc;

    public static final Object getInstance() {
            if(mc == null) {
                mc = new MyClass();
            }
            return mc;
    }

}

当然,这在一般的多线程场景中是行不通的。但请考虑以下情况:

  • 一开始只有一个线程
  • 这个线程getInstance()第一次调用,以便初始化 mc。
  • 之后,所有其他线程都由第一个线程启动。

我的假设:

这应该起作用,因为mc字段的初始化和对象的构造发生在启动其他线程的所有后续Thread.start()调用之前。并且Thread.start()线程发生在该线程的所有其他操作之前。它遵循mc在所有其他线程中的所有操作之前发生的初始化,以便getInstance()为所有线程返回正确的值。

这个假设正确吗?为什么/为什么不?

4

1 回答 1

5

你的分析确实很好。

准确地说:在一个线程上顺序发生的所有事情都有先发生的关系(显然,这样说:“如果 x 和 y 是同一个线程的操作,并且 x 在程序顺序中位于 y 之前,那么 hb(x, y)。”)

JLS 的 17.4.5 然后继续说以下内容:

“线程上的 start() 调用发生在已启动线程中的任何操作之前。”

因此,在单例实例化和已启动线程之间的顺序之前有一个明确的发生,因此它们可以保证看到最新的值。

简单地说:一个创建的线程保证可以看到它的父级在创建之前所做的一切,否则并发编程几乎是不可能的。

于 2014-11-06T22:53:17.657 回答