【问题标题】:Get and Put to Map at same time in Java在 Java 中同时获取和放置到地图
【发布时间】:2015-09-15 13:08:00
【问题描述】:

我有一个疑问。如果我在将一些数据放入地图的同时从地图中获取会发生什么?

我的意思是如果map.get()map.put() 同时被两个独立的进程调用。 get() 会等到put() 执行完毕吗?

【问题讨论】:

标签: java dictionary concurrency


【解决方案1】:

这取决于您使用的 Map 实现。

例如ConcurrentHashMap支持全并发,get()不会等待put()被执行,在Javadoc中有说明:

 * <p> Retrieval operations (including <tt>get</tt>) generally do not
 * block, so may overlap with update operations (including
 * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results
 * of the most recently <em>completed</em> update operations holding
 * upon their onset.

其他实现(如HashMap)不支持并发,不应由多个线程同时使用。

【讨论】:

  • "不应该被多个线程同时使用" ...没有额外的同步。
  • @DanAllen 确实如此,但由于已经有标准实现支持并发,因此使用基本类和添加自定义同步的动机较少。
  • 我同意,除非地图是某个更大对象的内部状态的一部分,该对象本身具有围绕它的同步。地图作为内部对象和并发交互的暴露点都非常常见。
【解决方案2】:

它可能会抛出 ConcurrentModificationException - 不确定。使用 synchronizedMap 总是更好。这通常是通过在一些自然封装地图的对象上同步来完成的。如果不存在这样的对象,则应使用 Collections.synchronizedMap 方法“包装”地图。最好在创建时完成,以防止对地图的意外不同步访问:

Map map = Collections.synchronizedMap(new HashMap(...));

【讨论】:

    【解决方案3】:

    Map 是一个接口,因此答案取决于您使用的实现。

    一般来说,这个接口的简单实现,例如HashMapTreeMap不是线程安全的。如果您没有围绕它们构建一些同步,同时puting 和geting 将导致未定义的行为 - 您可能会获得新值,您可能会获得旧值,很可能您只是获取ConcurrentModificationException,或者更糟的。

    如果您想处理来自不同线程的相同Map,请使用ConcurrentMap 的实现之一(例如,ConcurrentHashMap),这可以保证发生前发生序列(即,如果getput 之前被触发,即使put 正在进行,您也会得到旧值,反之亦然),或者同步Map 的访问(例如,通过调用@987654326 @。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-24
      • 1970-01-01
      • 2019-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-08
      • 1970-01-01
      相关资源
      最近更新 更多