2015-07-22 38 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。該頁面很好地解釋了它是如何替代您所提到的雙重鎖定機制。