2012-03-23 72 views
5

我想我可以用任何物体来进行同步的块如:如何判断在java线程中要同步哪个对象?

synchronized(new Object()){ 
} 

,但我经常看到一个同步的HashMap时需要的HashMap是线程safe.but我想我可以用一个其它的对象,而不是的散列图。那么哪个对象最好同步呢?

回答

12

synchronized (new Object()) { ... }是没有用的根本,因为没有其他线程将永远得到它反正锁定的对象保持。

你应该对象“守卫”的资源上进行同步。很显然,如果有多个线程需要访问相同的资源,则守护资源的对象需要可用于两个线程。

也许你已经看到了这一点:

class SomeClass { 

    final private Object lock = new Object(); 

    void method() { 
     ... 
     synchronized (lock) { 
      ... 
     } 
     ... 
    } 
} 

当然,这是从,因为在上面的代码做synchronized (new Object())很大的不同,同一个对象被用于执行方法的所有线程。

但我常常看到一个同步的HashMap时需要的HashMap是线程safe.but我想我可以用一个其它的对象,而不是HashMap中。那么哪个对象最好同步?

吧,如果哈希映射为多个线程之间共享资源,那么它是常见对该对象进行同步。

synchronized (someHashMap) { 
    ... use someHashMap in a thread safe way ... 
} 

是的,你也可以同步一些成员字段lock = new Object()以及。事实上,使用专用锁对象进行同步有时是首选,因为它不会影响您保护的对象的同步方法。

+0

非常感谢你! – jiafu 2012-03-23 14:37:21

+0

不客气:-) – aioobe 2012-03-23 14:39:13

6

每次使用新对象进行同步不会使线程更安全。您需要每次重用相同的同步对象。

其他然后,你可以使用另一种“同步对象”比你锁定的数据结构(但你需要确保你使用相同的参考无处不在;!))。


事实上,许多使用专用同步对象(例如private final Object sync = new Object())的对象中,因为同步this可能是危险的,当另一个线程可以在代码的其他地方锁定的对象。

+0

非常感谢你。你的意思是?我可以使用任何对象作为同步对象,但我应该保持同步目标是其他代码中的一些,如果我想要安全吗? – jiafu 2012-03-23 14:35:58

+0

您将需要使用*相同*锁定机制来保护您通过多个线程触摸的数据结构。如果使用需要锁定完全相同引用的'synchronized'块。 – dacwe 2012-03-23 14:38:44

+2

+1在与已知类而不是专用对象同步时,您应该小心,除非您确切知道该类所具有的功能。如果该类具有内置的某种同步,则可能导致与该类内部的代码发生冲突,从而与该类自身同步。 – 2012-03-23 14:55:21

2

它真的不重要,只要你每次都使用同一个。我个人比较喜欢使用需要同步(如您的HashMap),因为它传达更清楚,我是同步的实际的对象,并且不需要另一个对象实例(可能凌乱变量)。

请注意,如果你实际使用:

synchronized(new Object()) { 
    // ... 
} 

,那么你就错了,因为new Object()创建一个新的对象,每次;您需要保持相同的参考才能正确同步。

+0

非常感谢你! – jiafu 2012-03-23 14:53:23

3

首先,做synchronized(new Object())是一个坏主意,因为每个线程都会创建自己的对象,所以同步就没有意义。

在希望同步访问现有对象的示例中,对该对象进行同步是有意义的。创建一些其他对象进行同步没有任何好处。然而,如果你想做更多的事情来提高并发性 - 比如说把地图可能的键分成几组,然后用不同的锁保护每一组 - 然后创建单独的组合要同步的对象可能很有用。但是,除非您真的确定了需要解决的性能问题,否则我不会为此类问题而烦恼。

+0

-1代表“创建一些其他对象进行同步没有任何好处。”如果你同步到一个在它自己的方法中同步自己的现有对象,那么你可能会导致死锁而没有意识到它。 – 2012-03-23 14:56:57

+0

@ErickRobertson - 哈?死锁要求在两个不同的对象上获取锁。如果一个线程获得对象A的锁定,然后调用该对象中的同步方法,它已经保存了锁定,所以没有问题。 – 2012-03-23 15:03:51

+0

在多线程系统中,其他线程也可能与该对象交互。有几种方法可能是另一个线程可能已经锁定了对象,并尝试获取第一个线程在尝试同步到该对象时已拥有的锁定。 – 2012-03-23 16:23:46

3

似乎没有人提及它,但根据您的要求,首先使用线程安全对象可能使您可以删除所有锁定逻辑。

HashMap的情况下,有ConcurrentHashMap,它是一个线程安全版本,具有一些额外的原子操作(putIfAbsent等)。