【问题标题】:Double Locking on Normal Map - Is this Safe?法线贴图上的双重锁定 - 这安全吗?
【发布时间】:2016-12-02 16:12:06
【问题描述】:

大部分访问是读取,地图本身相对较小。也就是说,以下内容是否安全,我的测试表明结果比 ConcurrentHashMap 更快(至少在 1.7 倍上)。

   volatile Map<String, Object> mapV;

   public Object getV(String key) {
         Object value = mapV.get(key);
         if (value == null) {
                synchronized(this) {
                       value = mapV.get(key);
                       if (value == null) {
                             value = new Object();
                             Map<String, Object> copy = new HashMap<String, Object>();
                             copy.putAll(mapV);
                             copy.put(key, value);
                             mapV = Collections.unmodifiableMap(copy);
                       }
                }
         }
         return value;
   }

【问题讨论】:

  • 您尝试过Collections.synchronizedMap() 实现吗?它使用大致相同的系统,并且比 ConcurrentHashMap 更快(相对较小)
  • @n247s 我认为它们完全不同。同步的地图将强制锁定每次获取。这仅在辅助获取上强制锁定。代价是我在引入新密钥时需要重新复制所有内容。
  • 你真的需要写时复制吗?
  • @JimmyB 由于地图不是线程安全的,是的,您按照 John Vint 的确认进行操作。如果我们直接修改地图,Volatile 不会给我们任何帮助。

标签: java performance concurrency


【解决方案1】:

这将是线程安全的。由于您的映射分配是易失性的,任何看到mapV.get(key) != null 的线程都会遇到易失性读取,因此是安全的。

作为一个编辑:如果这实际上更快或者如果它会更快地处理大量数据,我会感到惊讶。我肯定会使用ConcurrentHashMap 而不是这个实现。

【讨论】:

  • 如果数据不多,SynchronizedHashMap(使用Collections.synchronizedMap(new HashMap&lt;&gt;()) 检索)比ConcurrentHashMap 快。更具体地说,如果只有一个线程同时访问映射,则与支持 Map 实现相比,性能没有显着提高。所以对于线程安全低流量的实现,SynchronizedHashMap 是要走的路。否则,ConcurrentHashMap 是首选。 (注意,Collections 类返回的SynchronizedHashMap 的迭代需要用户自己实现。)
  • 我不同意你的观点。 ConcurrentHashMap 就像普通的HashMap 一样,可能还会增加读取的易失性负载。他们都使用synchronized 进行互斥,因此任何优化都是相同的。在我看来,确实没有充分的理由使用synchronizedMap 而不是ConcurrentHashMap
  • 在大多数情况下,ConcurrentHashMap 就可以了。差异完全取决于数据量、访问线程的数量和操作类型。这是一篇关于此主题的文章,分析了不同的操作及其性能。 gregluck.com/blog/archives/2009/06/…
  • 我会完整阅读这篇文章。然而,这是在 2009 年编写的,并且 ConcurrentHashMap 进行了重大更新以解决空间问题(归因于 Segments 是 AbstractQueuedSynchronizer)。我希望看到更新的 ConcurrentHashMap 的更新。
  • 没错,我忘记了那个问题。在这种情况下,再次对这两种实现进行基准测试可能是值得的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-14
  • 1970-01-01
  • 1970-01-01
  • 2011-10-07
  • 2011-10-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多