2014-05-06 69 views
2

我已經宣佈枚舉,這是什麼樣子(並非真正的代碼)鎖定與更新直接

public enum MySession { 

    INSTANCE; 

    MySession() { 
     loadFactory(); 
    } 

    public void refreshMyFactory() { 
     //Is it OK to call "loadFactory" here as-is, or should I worry about concurrency 
    } 

    private void loadFactory() { 
     MyFactory factory = null; 
     try { 
      //Initialize factory by doing some IO. 
     } catch (final Exception exception) { 
      //Handle Exception 
     } finally { 
      myFactory = factory; 
      //If NULL, log FATAL exception... 
     } 
    } 

    private MyFactory myFactory; 

    /** 
    * @return the sessionFactory 
    */ 
    public MyFactory getMyFactory() { 
     return myFactory; 
    } 

} 

有可能訪問MySession.INSTANCE.getMyFactory多線程()和使用工廠。 工廠通過從輸入流中讀取文件來創建。

用例是我需要以編程方式刷新此工廠。

問題:

有沒有辦法鎖定對工廠的訪問,直到它被更新?這會有多混亂?

可以簡單地更新工廠,沒有任何鎖定。這樣做的含義是什麼?

回答

0

替換下面的代碼片段:

private void loadFactory() { 
    ... 
    myFactory = factory; 
} 
private MyFactory myFactory; 
public MyFactory getMyFactory() { 
    return myFactory; 
} 

有:

private void loadFactory() { 
    ... 
    myFactoryRef.set(factory); 
} 
private AtomicReference<MyFactory> myFactoryRef; 
public MyFactory getMyFactory() { 
    return myFactoryRef.get(); 
} 

,你不需要任何額外的同步打擾。 atomic reference可確保對變量的更新是原子的。 所以其他調用getMyFactory()的線程將會看到舊實例或MyFactory的新實例,並且在loadFactory()refreshMyFactory()中不需要額外的同步。

+0

雖然彼得的答案相當簡潔,但我會接受這個答案,因爲它提供了一種更簡單的方式來處理更新,而不使用volatile。 – Serendipity

2

有沒有辦法鎖定對工廠的訪問,直到它被更新?這會有多混亂?

您可以使getMyFactoryloadFactory同步。

可以直接更新工廠,沒有任何鎖定。這樣做的含義是什麼?

您需要使myFactory易失性以確保可以看到更改。其含義是你不需要任何其他操作來保證線程安全。即代碼你有,它的罰款。

+0

我可以讓getMyFactory和loadFactory同步,但是假設它不一定會阻止ThreadA在ThreadB加載工廠時得到工廠,對吧? – Serendipity