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

并发添加非线程安全的HashSet-可能发生的最坏情况是什么?

云瑞
2023-03-14
问题内容

情况:

多个线程仅将值添加到非线程安全的对象上,java.util.HashSet并且在Set这些线程停止之前,不会对进行任何其他操作。

题:

可能发生的最坏情况是什么?


问题答案:

这取决于您认为“最差”的情况。

我不确定这个问题是否旨在对当前实现进行详细的技术分析,同时考虑所有可能的竞争条件和Java内存模型的实质内容。

因此,如果问题是:“ 在当前的实现中可 证明 会发生什么?”
然后我必须说:“我不知道”。而且我认为几乎没有人确切地知道这一点。(这有点像问“当您以100
mph的速度撞墙后,您的汽车的哪个部分会坏?”-好吧,也许方向盘仍然完好无损,但这有关系吗?)

但是,如果问题是“在访问HashMap具有多个线程的非线程安全的存储器时,不太可能发生什么?” 那么有很多可能的答案:

  • 死锁
  • 例外情况
  • 缺少元素
  • 元素被多次插入
  • 元素被插入错误的哈希箱

(大致由我对“不良”的主观解释命令…)

编辑:注释的澄清:当然,如果插入元素的调用发生多次,则只能将元素添加两次。根据规范,HashMap最多应包含每个密钥 一次
。但是,将新条目添加到HashMap最终代表该调用的调用

void createEntry(int hash, K key, V value, int bucketIndex) {
    Entry<K,V> e = table[bucketIndex];
    table[bucketIndex] = new Entry<>(hash, key, value, e);
    size++;
}

并且没有(显而易见的)原因,为什么没有其他线程会table在此方法的第一行和第二行之间引起哈希(并因此创建新数组)。那么bucketIndex此调用的将会是错误的。然后再次添加该条目时,它可以使用(then)
right bucketIndex,因此以后将在地图中包含 两次

但是,再次重申:为了真正 证明 这种情况可能发生,必须对实施进行详细研究,这几乎是不可行的。最重要的是:将具有多个线程的元素添加到非线程安全时,基本上
任何事情 都会出错HashMap



 类似资料:
  • 问题内容: 我们有多个线程调用上。 我的理论是,当由两个线程同时调用时,实际上仅将要添加的两个对象之一添加到。这看似合理吗? 如果是这样,您如何解决呢?使用类似吗? 问题答案: 对于ArrayList上的两个线程同时调用add时发生的情况,没有任何保证的行为。但是,根据我的经验,两个对象的添加都很好。与列表相关的大多数线程安全问题在添加/删除时都会处理迭代。尽管如此,我强烈建议不要将Vanilla

  • 我看到了不同的PHP二进制文件,比如非线程或线程安全? 这是什么意思? 这些软件包之间有什么区别?

  • 简介 我们知道,JDK提供了线程安全的HashMap:ConcurrentHashMap,但是没有提供对应的ConcurrentHashSet,Hutool借助ConcurrentHashMap封装了线程安全的ConcurrentHashSet。 使用 与普通的HashSet使用一致: Set<String> set = new ConcurrentHashSet<>(); set.add("a"

  • tcp套接字是具有双向读写功能的endpoint。在java中,我们可以获得套接字的InputStream和OutputStream。 同时使用这些流是否安全? 据我所知,有一个连接能够在任何给定时间从一个endpoint发送或接收到其他数据。 我正在基于SocketChannels实现nio传输层,我想保留一个线程用于所有写入,一个线程用于接受和读取,但我不确定如果我的线程同时尝试在同一个套接字

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