2014-11-04 31 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