2013-08-21 81 views
0

是否有確保通過一個線程揮發性靜態成員變量運行一組方法的一種方式將完成,並在與之前其他線程上網本成員變量?我正在嘗試這樣的事情,但我不確定它會起作用。確保初始化方法成員變量之前完全被訪問

public class MyClass 
{ 
    private static final Object lock = new Object(); 
    public static volatile MyObj mo; //assume null will be checked before access 

    public static void initialize() 
    { 
    if (mo == null) 
    { 
     synchronized(lock) 
     { 
     mo = new MyObj(); 
     mo.doInit(); 
     mo.doMoreInit(); 
     } 
    } 
    } 
} 
+2

您正在尋找'Singleton'模式,並且此代碼不會**正確執行任何操作。 – OldCurmudgeon

+0

你打算實施單身模式嗎?你的'mo'字段可以被替換爲現在的狀態,所以我不確定你在問什麼 –

回答

1

您需要延遲的mo分配到後被調用的所有方法(即使用一個局部變量,然後分配mo作爲最後步驟)。

請注意,您基本上實現了雙重檢查鎖定(儘管使用volatile會使其「正確」工作)。您需要再次檢查mo爲空以內的的同步塊。

此外,還有一些其他(稍好些)模式,例如使用類初始化模式來管理同步。幾乎每一個可以想象的模式在這裏詳述http://en.wikipedia.org/wiki/Singleton_pattern

+0

你能否在你的答案中展開其他模式?謝謝。 – ADTC

0

你可以設置一個getter並有一些標誌,它檢查以確保執行任何方法。 getter可以等待執行完成以啓動所需的方法本身。

+0

是不是有一種基於同步的解決方案,它只是簡單地鎖定變量,直到初始化完成?一些不需要改變成員變量的訪問方式(想象代碼中有數百個地方)。 – ADTC

+0

@ADTC:不是我所知道的。 – npinti

1

您正在尋找Singleton模式,使用雙重檢查鎖定成語:

private static volatile MyObj obj = null; 

public static MyObj getObj() { 
    if (obj == null) { 
     synchronized (MyClass.class) { 
      if (obj == null) { 
       obj = new MyObj(); 
      } 
     } 
    } 
    return obj; 
} 

注意該字段是私有的,訪問一個爭奪的方法getObj() (並且只能通過這種方法)。如果某個字段是公共的,任何線程都可以隨時訪問它:您不能將訪問同步到字段中,而無需在方法後面封裝其訪問。

有更簡單的方法來獲得這個保證,但是如果你想延遲初始化,所有的AFAIK都需要調用一個方法。

+0

jtahlborn建議的_delayed assignment_怎麼樣?我想要一個不需要改變成員變量訪問方式的解決方案。 – ADTC

+0

通常應避免公共領域。公共靜態非final字段應該避免更多。當多線程發揮作用時,它們是一個更大的禁忌。做正確的事情,並避免它們。 –

+0

是的,我知道你的意思,但我正在處理的代碼不是我自己的。很多糟糕的開發人員都在做這件事,它很老,生疏,一團糟。將該字段更改爲私有和使用方法訪問將會很昂貴。 – ADTC

相關問題