【问题标题】:Does the static ConcurrentHashmap needs external synchronisation静态ConcurrentHashmap是否需要外部同步
【发布时间】:2011-07-07 10:23:21
【问题描述】:

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

【问题讨论】:

    标签: java synchronization concurrenthashmap


    【解决方案1】:

    是的,不是的。这取决于你在做什么。 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

    【讨论】:

      【解决方案2】:

      如果你需要获取集合的锁,你只需要外部同步。集合不会暴露其内部锁。

      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;
           }
       }
      

      【讨论】:

        【解决方案3】:

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

        http://download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/ConcurrentHashMap.html 上面写着:

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

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

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

        【讨论】:

          【解决方案4】:

          否:不需要外部同步。

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

          【讨论】:

          • 线程安全并不意味着您不需要在外部进行同步。我们需要知道地图的用途。 (出于同样的原因,Java 中引入了非同步集合类,因为原始类的“线程安全性”几乎是不必要且不足的)。
          • 我无法从问题中挑选出任何使用信息,当然不足以对某人投反对票。
          • 这是一个“相对不赞成票”,使其与彼得的回答处于同一水平。如果可以的话,我会投票给他两次。
          猜你喜欢
          • 2014-11-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-10-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多