当前位置: 首页 > 面试题库 >

HashMap对于不同的密钥是线程安全的吗?

仇经武
2023-03-14
问题内容

如果我有两个多个线程访问HashMap,但要保证它们永远不会同时访问同一密钥,那是否还会导致争用情况?


问题答案:

在@dotsid的回答中,他说:

如果你以任何方式更改HashMap,则代码将被破坏。

他是正确的。即使线程使用的是不相交的键集,在没有同步的情况下更新的HashMap也会中断。这是一些可能出错的事情。

  • 如果一个线程执行put,则另一线程可能会看到哈希图大小的陈旧值。

  • 当一个线程执行put触发表重建的操作时,另一个线程可能会看到哈希表数组引用的瞬时或陈旧版本,其大小,其内容或哈希链。可能会发生混乱。

  • 当线程对put与其他线程使用的某个密钥冲突的密钥执行a操作put,而后一个线程对其密钥进行操作时,则后者可能会看到哈希链引用的陈旧副本。可能会发生混乱。

  • 当一个线程使用与其他某个线程的键之一冲突的键探测表时,它可能会在链上遇到该键。它将在该键上调用equals,如果线程不同步,则equals方法可能在该键上遇到陈旧状态。

并且,如果你有两个线程同时执行put或remove请求,则有很多竞争条件的机会。

我可以想到三种解决方案

  1. 使用ConcurrentHashMap
  2. 使用常规HashMap但在外部同步;例如使用原始互斥量,Lock对象等。
  3. HashMap为每个线程使用不同的名称。如果线程确实有一组不相交的键,那么(从算法角度而言)应该不需要它们共享单个Map。确实,如果你的算法包含线程在某个点迭代映射的键,值或条目,则将单个映射拆分为多个映射可以显着加快该部分处理。


 类似资料:
  • 问题内容: 很简单,可以从多个线程中使用一个实例(例如),还是需要将多个实例放在一个线程中? 问题答案: 不,不是。该实例是有状态的。因此,您需要将其存储在threadlocal中,或者在每次加密/解密调用中获取一个新实例,或者将其包装在一个块中。 Threadsafety通常在Javadoc中提到“ 是线程安全的 ”或“ 是 不是 线程安全的 ”。情况并非如此,因此您不应假定它是线程安全的。

  • 我正在使用 okHttp 库来管理我的网页托管连接。所以我的问题是我不确定okHttp是否是线程安全的。 我的意思是,如果发送一些数据,同时服务器应用程序向我的客户端应用程序发送数据,okHttp应该接收这些数据,它会抛出异常吗?

  • 问题内容: 阅读“实践中的Java并发性”,第3.5节包含以下内容: 除了创建两个的明显的线程安全隐患外,该书还声称可能会发生发布问题。 此外,对于诸如 一个可以扔! 这怎么可能?我能想到的唯一允许这种荒谬行为的方法是,如果构造函数不被阻塞,那么当构造函数代码仍在另一个线程中运行时,将创建对实例的引用。 这可能吗? 问题答案: 之所以可行,是因为Java的内存模型较弱。它不保证读写顺序。 可以通过

  • 在我的应用程序中,我使用多个线程来处理客户端连接。 我在调试时发现了一个非常奇怪的行为——我有一个SelectionKey,通过调用(使用调试器)它的interestTops()方法,返回值是1(READ),但当我将数据发送到与该键对应的套接字时,选择器不会被唤醒。。 如果使用调试器,我将特定选择键更改为1(即使是1),选择器会突然对该更改做出反应。 在给定的时间内,我只有一个线程处理一个连接,但

  • 问题内容: Spring对象是线程安全的吗?如果没有,如何使它们线程安全? 问题答案: 这是两个不相关的问题: spring线程安全吗? 没有。 Spring具有不同的bean 作用域(例如Prototype,Singleton等),但是所有这些作用域都是在创建bean 时强制执行的。例如,每次“注入”一个“原型”范围的bean都会被创建,而一个“单个”范围的bean将被创建一次并在应用程序上下文

  • 在并发情景下,如果只用HashMap的get方法(不用put),因为我的Map是放配置数据的,启动完成后里面的数据不会改变,线程是否安全?