2014-11-04 67 views
0

我認爲以下用法是創建一個同步塊,因爲ThreadMyClass.class是唯一的。 但是,當我創建了一個多線程訪問方法的交通繁忙時,我發現有很多不一致的狀態被創建。 那麼爲什麼線程與ThreadMyClass.class實例不同步呢?線程同步塊與類本身

public ThreadMyClass { 


public Object get(){ 

    synchronized (ThreadMyClass.class) { 
    //get object return 
    } 

} 
} 


public static final Object lock = new Object(); 

當我已經改變ThreadMyClass.classlock對象,一切工作正常。

已更新: 這裏是我的完整代碼部分實例創建塊被調用多次。

public static XmppInterface getInstance() throws XMPPException { 
     if (instance == null) { 
     synchronized (XmppInterface.class) { 
      if (instance == null) { 
       //create an instance 
      } 
     } 
     } 
     return instance; 
    } 
+1

我沒有看到這個代碼的問題。如果我沒有弄錯,你的'get'-implementation應該等同於'public static synchronized Object get(){/ * get object return * /}'。也許導致這些暴力事件的原因在於你沒有顯示的代碼?難道你不能展示一個完整的最小工作示例來展示這些問題,即添加線程創建,調用'get'和最小'get'-implementation? – 2014-11-04 14:51:18

+1

另一個不使用類對象作爲鎖的原因是,其他類可以嘗試同步它。潛在的死鎖和延誤。 – TedTrippin 2014-11-04 15:20:40

+0

不幸的是,我無法重現一個不一致的狀態。你的代碼對我來說看起來很好,但也許我只是沒有看到錯誤。但是,由於您似乎試圖在'XmppInterface'上強制使用Singleton屬性,因此您還可以使用枚舉來解決此問題:查看Effective Java中的Item 3:http://uet.vnu.edu.vn/ 〜chauttm/e-books/java/Effective.Java.2nd.Mdition.2008.3000th.Release.pdf – 2014-11-04 15:21:37

回答

2

好吧,你同步在class,而不是它的實例,這無異於具有static synchronized方法。

要同步您班級的實例,您可以使用​​實例方法。

否則,通過用於鎖的Object進行同步僅會在該Object上進行同步,而將其餘靜態方法和實例方法從同步策略中「釋放」。

+0

,我的用法是正確的。我正在使用ClassLevel鎖定。 http://howtodoinjava.com/2013/03/08/thread-synchronization-object-level-locking-and-class-level-locking/ – 2014-11-04 20:06:53

+1

@ mmc18有一個快速瀏覽文章。它基本上強調了它所謂的「對象級鎖定」(它似乎包括對象鎖定和實例鎖定)和類級鎖定之間的區別。還有其他一些沒有說明的習慣用法,例如使用實際的'java.util.concurrent.locks.Lock'等。這一切都取決於上下文以及你想實現的目標。 – Mena 2014-11-04 20:31:59