2015-07-22 34 views
1

虽然多线程读取,我才知道,辛格尔顿需要有双锁检查,并声明为volatile单引用,这样是Java ClassLoading SingleThreaded?

  1. 同步开销,避免
  2. 多线程没有创建辛格尔顿的多个实例正在考虑的类别 请参阅这个博客。 http://javarevisited.blogspot.sg/2014/05/double-checked-locking-on-singleton-in-java.html

在我的脑海里有这些问题,

如果类加载是单线程的,为什么我们关心的多线程问题?

静态初始化块恰好在应用程序生命周期中执行一次,那么为什么不使用静态初始化程序创建一个singletone?

+0

一般而言,您应该[将多个问题视为多个帖子](https://meta.stackexchange.com/questions/39223/one-post-with-multiple-questions-or-multiple-posts)。 – Jeffrey

回答

2
  1. 班级负载为not necessarily single threaded。由于Java 7,ClassLoader可以将自己标记为parallel capable
  2. 在静态初始化器中实例化一个单例很好。主要缺点是这些初始化是eager,而不是lazy。这可以通过使用initialization on demand idiom来缓解。但请注意,可以通过创建自定义ClassLoader两次运行静态初始化器。
+0

我在这里浏览了Java语言规范:http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html 就像你说的,类加载是多线程的,但是如果后续线程看到该类已经被初始化,它不会再次初始化该类,如12.4.2节所述。详细的初始化过程在同一个URL上。 – Nealesh

+0

@Nealesh你是对的。标准的'ClassLoader's不会加载两次相同的类。然而,即使另一个'ClassLoader'已经加载了这个类,你也可以创建一个自定义的'ClassLoader',它总是从头开始定义一个类。 – Jeffrey

1

这是真的,你说得对,静态初始化块只发生一次。事实上,这是懒惰的;它只会在课程实际需要时才运行。因此,人们可以简单地直接实例化一个对象并为其获取一个对象。这是使用«初始化按需持有人成语»证明:

private static class LazySomethingHolder { 
    public static Something something = new Something(); 
} 

public static Something getInstance() { 
    return LazySomethingHolder.something; 
} 

更多信息请参见http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#dcl。该页面很好地解释了它是如何替代您所提到的双重锁定机制。