加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java是否具有静态顺序初始化失败?

发布时间:2020-12-14 05:53:25 所属栏目:Java 来源:网络整理
导读:这里最近的一个问题是具有以下代码(和类似的)来实现没有同步的单例. public class Singleton { private Singleton() {} private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton get
这里最近的一个问题是具有以下代码(和类似的)来实现没有同步的单例.
public class Singleton {
    private Singleton() {}
    private static class SingletonHolder { 
        private static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

现在,我想明白这是做什么的.由于实例是静态final,所以在任何线程调用getInstance()之前建立很久,所以不需要同步.

只有当两个线程同时尝试调用getInstance()时,才需要同步(该方法在第一次调用时进行构造,而不是“静态最终”).

因此,我的问题基本上是:为什么你会喜欢懒惰地建造单身人士呢?

public class Singleton {
    private Singleton() {}
    private static Singleton instance = null;
    public static synchronized Singleton getInstance() {
        if (instance == null)
            instance = new Singleton();
        return instance;
    }
}

我唯一的想法是,使用静态最终方法可能会引入排序问题,如C静态初始化顺序失败.

首先,Java实际上有这个问题吗?我知道一个类中的顺序是完全指定的,但它以某种方式保证了类之间的一致顺序(例如使用类加载器)?

其次,如果订单是一致的,为什么懒惰的施工方案有利于?

解决方法

Now,I think understand what this is doing. Since the instance is static final,it’s built long before any threads will call getInstance() so there’s no real need for synchronisation.

不完全的.它是在SingletonHolder类为initialized时构建的,这是在第一次调用getInstance时发生的.类加载器具有单独的锁定机制,但在加载类之后,不需要进一步的锁定,因此该方案只需要足够的锁定来防止多个实例化.

First off,does Java actually have this problem? I know order within a class is fully specified but does it somehow guarantee consistent order between classes (such as with a class loader)?

Java确实有一个问题,即类初始化周期可能导致某些类在初始化之前观察另一个类的静态决赛(技术上在所有静态初始化程序块运行之前).

考虑

class A {
  static final int X = B.Y;
  // Call to Math.min defeats constant inlining
  static final int Y = Math.min(42,43);
}

class B {
  static final int X = A.Y;
  static final int Y = Math.min(42,43);
}

public class C {
  public static void main(String[] argv) {
    System.err.println("A.X=" + A.X + ",A.Y=" + A.Y);
    System.err.println("B.X=" + B.X + ",B.Y=" + B.Y);
  }
}

运行C打印

A.X=42,A.Y=42
B.X=0,B.Y=42

但是在您发布的成语中,助手和单例之间没有循环,所以没有理由更喜欢懒惰初始化.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读