2012-02-23 101 views
0

我有一個高併發系統類。該類的方法getResolvedClassName()可能會產生死鎖。所以我用以下方式設計它:高併發系統鎖定

public class ClassUtils { 

    private static ClassUtils classUtils; 

    private transient Object object = new Object(); 

    private synchronized Object getObjectLock() { 
     return object; 
    } 

    public void getResolvedClassName(Class<?> clazz) { 
     synchronized (getObjectLock()) { 
      //some job will be done here 
     }  
    } 

    public synchronized static ClassUtils getInstance() { 
     if(classUtils == null) { 
      classUtils = new ClassUtils(); 
     } 
     return classUtils; 
    } 
} 

我是否正確地做到了這一點?任何信息都會對我有所幫助。

謝謝。


編輯:

public class ClassUtils { 

    private static final ClassUtils classUtils = new ClassUtils(); 
    private ReentrantLock lock = new ReentrantLock(); 

    public void getResolvedClassName(Class<?> clazz) { 
     lock.lock(); 
     //some job will be done here 
     lock.unlock();  
    } 

    public static ClassUtils getInstance() {   
     return classUtils; 
    } 
} 
+0

其他人可能會不同意,但我認爲這個問題有點太模糊,不允許有用的答案。 – NPE 2012-02-23 17:50:50

+0

'私人臨時對象對象' - 不應該是'final'而是? – 2012-02-23 17:52:55

+1

使你的鎖'最終',而不是瞬態。刪除它的getter(直接在方法中使用該屬性)。您的單例初始化方法被破壞,使用雙重鎖定檢查或枚舉。看到這個頁面的更復雜的鎖類型: - http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/locks/package-summary.html – Perception 2012-02-23 17:56:33

回答

3

有幾件事情中脫穎而出:

  1. 我不認爲transient關鍵字means what you think it means。該關鍵字與同步無關,僅在序列化類時使用。您可能會將其與volatile混淆。順便提一下,這裏也不需要volatile

  2. 你的單例的懶惰初始化可能是不必要的。你爲什麼不做private static final ClassUtils classUtils = new ClassUtils();?然後你的getInstance()方法不需要同步,只需要return classUtils;它也是線程安全的。你也應該總是聲明單例實例爲final

  3. getObjectLock()的整個情況是不需要的。您只需在this上同步(即將getResolvedClassname轉換爲​​方法),並且將更安全,更清潔。

你也可以調查java.util.concurrent.Lock課程,看看是否有什麼比一個Object,這是時下視爲形式拙劣同步更適合。

+0

非常感謝。我編輯了我的問題並添加了代碼片段。現在好嗎? – 2012-02-23 18:18:00

+2

@TapasBose這是,但我不會使用'ReentrantLock'。使用'private final Object lock = new Object()'並且在其上進行同步會更簡單。如果你堅持使用'ReentrantLock',我建議兩件事:使字段最終,並將代碼放在'getResolvedClassName'到try-finally語句中。 'lock.lock()'應該是try塊中的第一個語句,'lock.unlock()'應該放在finally塊中。這樣做是爲了確保如果發生某種異常,鎖將被解鎖。 – Malcolm 2012-02-23 19:00:09

0

你的問題是有點一般。但是,您可以考慮將該值初始化爲不可變。許多不可變的初始值是線程安全的,並且不需要鎖定。

3

這個問題確實有點含糊,我沒有看到使用單例的目的以及爲什麼同步需要做一些工作。如果它不訪問可變狀態,則不需要同步。我只能說三個鎖(ClassUtils.classClassUtils實例和object)幾乎肯定會增加不必要的複雜性。另外,正如Justin指出的那樣,您最終應該製作object,那麼您將不需要同步來訪問它。