Java 静态初始值设定项线程安全吗?

我正在使用静态代码块来初始化我拥有的注册表中的一些控制器。因此,我的问题是,我能否保证在首次加载类时,此静态代码块将仅绝对调用一次?我知道我不能保证何时会调用此代码块,我猜它是Classloader首次加载它的时间。我意识到我可以在静态代码块中的类上进行同步,但我的猜测是这实际上是无论如何都会发生的事情吗?

简单的代码示例是;

class FooRegistry {

    static {
        //this code must only ever be called once 
        addController(new FooControllerImpl());
    }

    private static void addController(IFooController controller) { 
        // ...
    }
}

或者我应该这样做;

class FooRegistry {

    static {
        synchronized(FooRegistry.class) {
            addController(new FooControllerImpl());
        }
    }

    private static void addController(IFooController controller) {
        // ...
    }
}

答案 1

是的,Java 静态初始值设定项是线程安全的(使用您的第一个选项)。

但是,如果要确保代码只执行一次,则需要确保类仅由单个类装入器装入。静态初始化对每个类装入器执行一次。


答案 2

这是一个可用于延迟初始化的技巧

enum Singleton {
    INSTANCE;
}

或用于 Java 5.0 之前的

class Singleton {
   static class SingletonHolder {
      static final Singleton INSTANCE = new Singleton();
   }
   public static Singleton instance() {
      return SingletonHolder.INSTANCE;
   }
}

由于 SingletonHolder 中的静态块将以线程安全的方式运行一次,因此您不需要任何其他锁定。类 SingletonHolder 只有在调用 instance() 时才会加载


推荐