为什么这个静态最终变量在单例线程安全中?

阅读本网站,我发现了这个 :

[行] private static final Foo INSTANCE = new Foo(); 只有在实际使用类时才会执行,这会处理惰性实例化,并保证它是线程安全的。

为什么这保证是线程安全的? 因为这个领域是最终的 ? 还是出于其他原因?

因为它是最终的,是的。 最终变量具有特殊的线程安全语义,因为其他线程保证至少在其构造函数完成时看到最终字段。

这是在JLS 17.5中 ,虽然语言有点密集。 这些语义是在Java 1.5中引入的,特别是JSR-133 。 有关JSR-133及其各种含义的非规范讨论,请参阅此页面。

请注意,如果在构造函数之后修改实例,则不一定是线程安全的。 在这种情况下,您必须采取通常的螺纹安全预防措施,以确保发生在边缘之前。

我相当肯定(虽然不是100%)只有一个线程进行类初始化的事实不是这里的一个因素。 确实这个类只是由一个线程初始化,但是我不相信在该线程之间建立任何其他使用该类的线程的任何特定的发生 – 之前的边缘(除了那个其他线程不需要重新初始化)class级)。 因此,如果没有final关键字,另一个线程将能够看到对象的部分构造的实例。 JMM定义的特定发生前边缘在JLS 17.4.5中 ,并且那里没有列出类初始化。

保证类构造函数和静态/实例初始化程序是primefaces执行的,因为private static final FOO INSTANCE = new FOO; 相当于

 private static final FOO INSTANCE; static{ INSTANCE = new FOO(); } 

这种情况属于上述类别。

它保证是线程安全的,因为JVM保证在单个线程上执行静态初始化器。

这并不意味着Foo的实例在内部是线程安全的 – 它只是意味着你可以保证在一个线程上通过这个特定的代码路径只调用一次Foo的构造函数。

任何类的静态初始化块都保证是单线程的。 更简单的单例是使用枚举

 enum Singleton { INSTANCE; } 

这也是线程安全和类惰性初始化。