【发布时间】:2012-04-08 02:48:19
【问题描述】:
我想我可以使用任何对象作为块进行同步,例如:
synchronized(new Object()){
}
但我经常看到在需要 hashmap 是线程安全的时候同步一个 hashmap。但我认为我可以使用另一个对象来代替 hashmap。那么哪个对象最好同步呢?
【问题讨论】:
标签: java synchronized
我想我可以使用任何对象作为块进行同步,例如:
synchronized(new Object()){
}
但我经常看到在需要 hashmap 是线程安全的时候同步一个 hashmap。但我认为我可以使用另一个对象来代替 hashmap。那么哪个对象最好同步呢?
【问题讨论】:
标签: java synchronized
synchronized (new Object()) { ... } 一点用都没有,因为没有其他线程会获得被锁定的对象。
您应该在“保护”资源的对象上进行同步。显然,如果多个线程需要访问同一个资源,则保护该资源的对象需要对两个线程都可用。
也许你已经看到了:
class SomeClass {
final private Object lock = new Object();
void method() {
...
synchronized (lock) {
...
}
...
}
}
然而,这与 synchronized (new Object()) 非常不同,因为在上面的代码中,相同的对象用于执行该方法的所有线程。
但是当需要 hashmap 是线程安全的时,我经常看到同步一个 hashmap。但我认为我可以使用另一个对象来代替 hashmap。那么哪个对象最好同步呢?
是的,如果哈希映射是要在多个线程之间共享的资源,那么在该对象上进行同步是很常见的。
synchronized (someHashMap) {
... use someHashMap in a thread safe way ...
}
是的,您也可以在某些成员字段lock = new Object() 上进行同步。事实上,有时首选使用专用锁对象进行同步,因为它不会干扰您要保护的对象的同步方法。
【讨论】:
每次使用一个新对象进行同步并没有使任何线程更安全。您需要每次重复使用相同的同步对象。
除此之外,您可以使用另一个“同步对象”而不是您锁定的数据结构(但您需要确保在任何地方都使用相同的引用!;))。
事实上,许多人在对象中使用专用同步对象(例如private final Object sync = new Object()),因为当另一个线程可以在代码中的其他位置锁定对象时,同步this 可能会很危险。
【讨论】:
synchronized 块。
首先,做synchronized(new Object())是个坏主意,因为每个线程都会创建自己的对象,所以同步没有意义。
在您希望同步访问现有对象的示例中,在该对象上进行同步是有意义的。创建其他对象进行同步没有任何好处。
但是,如果您想做一些更花哨的事情来增加并发性——例如,将映射的可能键分成几组,并用不同的锁保护这些组中的每一个——然后创建单独的对象同步可能很有用。但在您真正确定需要解决的性能问题之前,我不会为此类事情烦恼。
【讨论】:
似乎没有人提到它,但根据您的要求,首先使用线程安全对象可能可以让您删除所有锁定逻辑。
在HashMap 的情况下,有ConcurrentHashMap,这是一个线程安全版本,带有一些额外的原子操作(putIfAbsent 等)。
【讨论】:
真的没关系,只要你每次都用同一个。我个人更喜欢使用需要同步的实际对象(例如您的HashMap),因为它更清楚地传达了我正在同步它,并且不需要另一个对象实例(可能带有混乱的变量)。
请注意,如果您实际使用的是:
synchronized(new Object()) {
// ...
}
那么你做错了,因为new Object() 每次都会创建一个新对象;您需要保持相同的引用才能正确同步。
【讨论】: