【问题标题】:Thread safe implementation for Hash MapHash Map 的线程安全实现
【发布时间】:2013-08-02 17:35:43
【问题描述】:

首先,我将描述我想要什么,然后我将详细说明我正在考虑的可能性。我不知道哪个是最好的,所以我需要一些帮助。

我有一个哈希映射,我在其上从Servlet 进行读写操作。现在,由于这个Servlet 在Tomcat 上,我需要哈希映射是线程安全的。基本上,当它被写入时,没有其他东西可以写入它,也没有任何东西可以读取它。

我见过ConcurrentHashMap,但注意到它的get 方法不是线程安全的。然后,我看到了锁和一种叫做同步的东西。

我想知道哪种方法最可靠。

【问题讨论】:

  • ConcurrentHashMap.get 在什么方面不是线程安全的?您在寻找什么级别的粒度? “何时写入”是指会有 多个 put 操作,还是每个都足够是原子的?
  • 看到 API 文档,我认为它不是线程安全的。如果说 3 个人决定执行相同的 put 操作,则哈希映射可以有多个 put 操作。
  • @pratnala 它允许并发操作的事实并不意味着它不是线程安全的。
  • 此外,如果正在将某些内容写入哈希映射,其他人应该无法读取它。 ConcurrentHashMap 能保证吗?
  • 从javadoc中不保证:检索操作(包括get)一般不会阻塞,因此可能与更新操作(包括put和remove)重叠。检索反映了最近完成的更新操作在开始时保持的结果。

标签: java thread-safety concurrenthashmap locks


【解决方案1】:

ConcurrentHashMap.get() 是线程安全的。

您可以通过用Collections.synchronizedMap() 包装HashMap 使其线程安全。

【讨论】:

  • 有什么区别?
  • @naXa ConcurrentHashMap 允许并发访问,而 synchronized 不允许。
【解决方案2】:

这是 ConcurrentHashMap 类的重点。当您拥有超过 1 个线程时,它可以保护您的收藏。

【讨论】:

    【解决方案3】:

    Collections.synchronizedMap(new HashMap<K, V>);

    返回由指定映射支持的同步(线程安全)映射。为了保证串行访问,所有对 backing map 的访问都必须通过返回的 map 完成。

    当迭代任何集合视图时,用户必须在返回的地图上手动同步:

    【讨论】:

    • “通过返回的排序映射完成对支持排序映射的所有访问至关重要”是什么意思?
    • 错误地复制了 Collection.synchronizedSortedMap() 的描述,我的意思是你传入的地图仍然不是线程安全的
    • 我还是没看懂描述。
    【解决方案4】:

    编辑:删除虚假信息

    无论如何,synchronized 关键字是一个安全的选择。它阻止任何线程在 synchronized 块内访问对象。

    // Anything can modify map at this point, making it not thread safe
    map.get(0);
    

    相对

    // Nothing can modify map until the synchronized block is complete
    synchronized(map) {
        map.get(0);
    }
    

    【讨论】:

    • 在一个容器中每个Servlet 都只有一个实例。所有映射的请求都将通过同一个实例。如果您有实例字段,那么每个请求都可以访问它们。
    • 请求在不同的线程中执行,即 servlet 的 service() 方法可以同时执行(除非 Servlet 被声明为 SingleThreadModel),尽管只有一个 servlet 实例。因此,在 Servlet 类中声明的实例变量可以从多个请求处理线程中调用。
    • 确认。你(都)是对的,我不知道我在想什么。我认为我们(在工作中)已经通过一些测试证明了这一点。我将删除我的答案的那部分。
    【解决方案5】:

    我建议您使用ConcurrentHashMap,您在上面提到的要求,之前我对我们的应用程序也有相同类型的要求,但我们更关注性能方面。

    我同时运行 ConcurrentHashMapColecctions.synchronizedMap(); 返回的地图,在各种类型的负载下使用 JMeter 一次启动多个线程,我使用 JProfiler 监控它们。在所有这些测试之后,我们得出的结论是该地图返回Colecctions.synchronizedMap() 在与ConcurrentHashMap 比较的性能方面效率不如ConcurrentHashMap

    我也写了一封post,关于我在这两个方面的经历。

    谢谢

    【讨论】:

      猜你喜欢
      • 2013-02-10
      • 2010-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-18
      相关资源
      最近更新 更多