2011-06-22 31 views
8

我試圖在我下面的代碼的對象上進行同步:NullPointerException異常的同步聲明

public void myMethod() { 
    synchronized (globalObj) { 
     //Do something here 
    } 
} 

的代碼是在一個線程中執行。問題是,另一個線程可能會將'globalObj'設置爲空。然後,'synchronized(globalObj)'將在其他線程將'globalObj'設置爲null時拋出NullPointerxception。

在對象上進行同步的最佳做法是什麼,所以NullPointerException不會被拋出?

謝謝。

+0

請更多代碼。 –

回答

25

您不應該同步本身可能會更改的引用。如果允許另一個線程替換globalObj,這意味着您可能會鎖定舊的globalObj而另一個線程在完全不同的線程上工作 - 該鎖完全無法幫助您。

你應該做的卻是有這個目的的單獨Object

static final Object lockObj = new Object(); 

public void myMethod() { 
    synchronized (lockObj) { 
    // do something with globalObj here 
    } 
} 

由於lockObj永遠不會改變,你會始終使用相同的鎖 - 沒有問題。

1

確保你的對象,不能爲null上同步...

你爲什麼要設置globalObj爲空?這應該是什麼併發語義?是不是偶然?

如果鎖定的必要性有時會消失(雖然看起來很奇怪),但您可以添加一個空檢查(當然,您需要同步其他某些內容以避免首先檢查null的競爭條件,然後之後立即將其設置爲空)。

請詳細描述您的情況。

0

創建一個私有對象類成員,它沒有任何公共setter並鎖定它。

6

您不能同步null參考。最佳做法是在final對象上進行同步(以確保它永遠不會是null),或者(更好地)使用java.util.concurrent程序包中更高級別的併發抽象。