当前位置: 首页 > 知识库问答 >
问题:

何时使用concurrenthashmap vs hashmap进行put和get

申思远
2023-03-14

在一个采访问题中,我被要求解释一种情况,即使用并发哈希图与使用哈希图相比是正确的方法。在板上有两列t1和t2(对应于thread1和thread2),我应该编写一系列操作(如map.put(2,10)map)。get(2)等)使用concurrenthashmap与hashmap将产生预期结果。

我试图用迭代器举一个例子,但这不是面试官想要的。他在为线程1和线程2寻找一系列的放和拿操作。他说假设我们从不迭代,我们只有放和拿操作。

我查看了SO上的其他线程,并验证了我的线程安全知识,但我仍然想不出任何put和get的例子,用hashmap产生错误的结果,用concurrenthashmap产生正确的结果。有没有什么放和拿的顺序,或者我应该说不可能?

共有2个答案

东郭阳德
2023-03-14

这是一个有趣的问题。

正确答案是:

在多线程场景中,对< code>ConcurrentHashMap执行的一系列get和put操作很少会产生预期的结果。除了< code>put()之外,您几乎总是需要使用原子的比较和变异操作,如< code > computeifaxine()来做任何有用的事情。一个例外是,当您将映射用作缓存时,让多个线程计算同一个条目的可能性比在一个线程执行时阻塞更有效...但是,您真的需要缓存吗?不经常。

仅供记录,如下所示:

Thread1 + Thread2 (they both do the same thing)
-----------------------------------------------

result = map.get(key);
if (result == null) {
    result = somewhat_expensive_function(key)
    map.put(key, result);
}
return result; 

另一方面,当一个线程可能正在修改映射而另一个线程也在使用时,在两个线程之间使用正常的<code>HashMap</code>可能会导致未定义的行为——结果与任何操作序列不一致、空指针异常,甚至是永久损坏的数据结构。

如果我在面试中问这个问题,我将测试的是:候选人是否理解使用线程安全的数据结构并不能使他的算法线程安全?

史和泰
2023-03-14

它们有许多不同的方式——由于HashMap没有受到防止来自多个线程的并发访问的保护,因此您可能会完全破坏其内部数据结构。

然而,大多数情况下,你会得到更多的良性影响。下面的代码应该把来自多线程的2000个条目放在每个映射中。但是对于散列表来说,在操作之后,映射中的条目会一直少于2000个,因为一些put会相互冲突,并且它们的结果会丢失。

public class BreakingMap {
    public static void testIt(Map<Integer, Integer> map) throws InterruptedException {
        IntStream.range(0, 2000).parallel().forEach(i -> map.put(i, -1));
        System.out.println(map.size());
    }

    public static void main(String[] args) throws InterruptedException {
        testIt(new HashMap<>());
        testIt(new ConcurrentHashMap<>());
    }
}
 类似资料:
  • 问题内容: 我已经使用JAX-RS(Jersey 2.0)实现了一个小的REST API,并且正在使用AJAX调用该API,GET和POST都可以正常工作,但是当我调用任何PUT或DELETE方法时,得到的只有以下内容错误信息: 加载资源失败:服务器的响应状态为403(禁止) 这是Java中 DELETE 方法的示例: 这是使用AJAX的Javascript调用: 任何帮助都感激不尽!!谢谢!!

  • 我正在尝试对put请求进行测试,它给了我空指针错误,只是在这种类型的请求中,我不知道为什么请有人帮我,这是我的控制器: 对于测试方法:

  • 如何使用curl测试RESTful PUT(或DELETE)方法?

  • 问题内容: 它应该是如此简单。我已经跟踪了所有可以找到的教程和论坛,但是无法正常工作。我只想在Apache2上用PHP构建RESTful API。 在我的VirtualHost指令中,我说: 但是我向服务器发出的每个PUT请求都得到了不支持的405方法。 有人提倡使用Script指令,但是由于我使用的是mod_php(而不是CGI),所以我不明白为什么会这样。 人们提到使用WebDAV,但在我看来

  • 问题内容: 如何使用Swift 进行倒数计时? 问题答案: 问题1: 问题2: 两者都可以。SpriteKit是用于场景,运动等的SDK。简单视图应用程序是项目模板。他们不应该冲突

  • 我最近一直在测试HashMap,我偶然发现了一个有趣的问题。我有一个数组,a3,我设置了一些任意值。然后,我获取此数组并将其放入 HashMap 实例映射中。 我的问题是,当我给一个对象实例赋put的值(“a3”,a3)时,我似乎无法打印出实例的地址。 例如: 当我调用System.out.println(map.put("a3", a3)时,我在内存中得到了一个地址。 然而,如果我创建了一个对象