class MyClass
{
  private static volatile Resource resource;

  public static Resource getInstance()
  {
            if(resource == null)
                      resource = new Resource();
            return resource;
  }
}

这里如果Resource是一个不可变的类,写上面的代码安全吗?与实践中的 java 并发一样,它提到“初始化安全性允许正确构造的不可变对象(immutable对象)在线程之间安全地共享。所以上面的代码可以安全地编写。” (在第 349 页 16.3 中)。但是,如果两个线程检查 null 并且它们可以继续创建对象,这可能会违反类的不变性(单例)。请解释。问题的延续
link

最佳答案

不,这不是线程安全代码。在这种情况下, Resource 可能是线程安全的,但您的 getInstance 方法不是。

想象一下这一系列的事件

Thread1 calls getInstance and checks "if resource == null" and then stops (because the OS said it was time for it to be done) before initializing the resources.

Thread2 calls getInstance and checks "if resource == null" and then initializes the instance

Now Thread1 starts again and it also initializes the instance.

它现在已经初始化了两次并且不是单例。

您有几个选项可以使其线程安全。
  • 使 getInstance 方法同步
  • 在声明时(或在静态初始化器中)初始化实例,getInstance 可以直接返回它。

  • 您也不需要使变量可变。在第 1 种情况下,无论如何同步该方法都会刷新变量,因此所有变量都将看到更新的副本。在第 2 种情况下,保证对象在构造后对所有对象可见。

    关于java - java中具有不可变类的单例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15079161/

    10-11 23:01
    查看更多