4

静态 ConcurrentHashmap 是否需要使用同步块或锁进行外部同步?

4

4 回答 4

4

是和不是。这取决于你在做什么。ConcurrentHashMap 的所有方法(例如get 和put)都是线程安全的。但是,对于非原子操作,它不是线程安全的。下面是一个执行非原子操作的方法示例:

public class Foo {
    Map<String, Object> map = new ConcurrentHashMap<String, Object>();

    public Object getFoo(String bar) {
        Object value = foo.get(bar);
        if (value == null) {
            value = new Object();
            map.put(bar, foo);
        }
        return value;
    }
}

这里的缺陷是两个线程调用getFoo接收不同的对象是可能的。请记住,在处理任何数据结构或类型时,即使像 . 一样简单int,非原子操作也总是需要外部同步。诸如 AtomicInteger 和 ConcurrentHashMap 之类的类有助于使某些常见操作线程安全,但不能防止getFoo上述检查然后设置操作。

于 2012-04-24T22:30:51.160 回答
3

如果您需要获取对集合的锁定,则只需要外部同步。该集合不暴露其内部锁。

ConcurrentMap 有 putIfAbsent,但是如果创建对象的成本很高,您可能不想使用它。

 final ConcurrentMap<Key, Value> map =

 public Value get(Key key) {
     // allow concurrent read
     return map.get(key);
 }

 public Value getOrCreate(Key key) {
     // could put an extra check here to avoid synchronization.
     synchronized(map) {
        Value val = map.get(key);
        if (val == null)
           map.put(key, val = new ExpensiveValue(key));
        return val;
     }
 }
于 2011-07-07T10:46:09.090 回答
0

据我所知,所有需要的锁定都是在这个类中完成的,这样你就不需要太担心它,以防你没有做一些特定的事情并需要它像那样工作。

http://download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/ConcurrentHashMap.html它说:

但是,即使所有操作都是线程安全的,检索操作也不需要锁定,并且不支持以阻止所有访问的方式锁定整个表。

检索操作(包括 get)一般不会阻塞,因此可能与更新操作(包括 put 和 remove)重叠。检索反映了最近完成的更新操作在其开始时保持的结果。

因此,如果这不代表您的特定应用程序中的任何问题,您无需担心。

于 2011-07-07T10:31:50.250 回答
-1

否:无需外部同步。

类上的所有方法java.util.concurrent都是线程安全的。

于 2011-07-07T10:27:33.173 回答