简体   繁体   English

何时使用 concurrenthashmap 与 hashmap 进行放置和获取

[英]When to use concurrenthashmap vs hashmap for put and get

In an interview question I was asked to explain a situation when using a concurrenthashmap would be the right way vs using a hashmap.在一个面试问题中,我被要求解释一种情况,即使用并发哈希图与使用哈希图相比是正确的方法。 On the board there were two columns t1 and t2 (corresponding to thread1 and thread2), and I was supposed to write a sequence of actions (like map.put(2, 10) , map.get(2) , etc) that using a concurrenthashmap vs a hashmap would produce the expected result.在板上有两列 t1 和 t2(对应于线程 1 和线程 2),我应该编写一系列操作(如map.put(2, 10)map.get(2)等),使用concurrenthashmap 与 hashmap 会产生预期的结果。

I tried to give an example with an iterator but that was not what the interviewer looking for.我试图用迭代器举一个例子,但这不是面试官想要的。 He was looking for a sequence of put and get operations for thread1 and thread2.他正在寻找线程 1 和线程 2 的放置和获取操作序列。 He said assume we never iterate and we only have put and get operations.他说假设我们从不迭代,我们只有 put 和 get 操作。

I looked at other threads on SO and verified my knowledge of thread safety but still I can't think of any example for put and gets producing wrong result with hashmap and correct result with concurrenthashmap.我查看了 SO 上的其他线程并验证了我对线程安全的了解,但我仍然想不出任何关于 put 的示例,并使用 hashmap 生成错误的结果,并使用 concurrenthashmap 生成正确的结果。 Is there any sequence of puts and gets, or I should have said not possible?是否有任何放置和获取的顺序,或者我应该说不可能?

There are many ways in which they can differ - since HashMap is not protected against concurrent access from multiple threads, you could breaks its internal data structure entirely.它们有很多不同的方式 - 因为 HashMap 没有保护免受来自多个线程的并发访问,您可以完全破坏其内部数据结构。

However must often you get more benign effects.但是,您必须经常获得更良性的效果。 The below code should put 2000 entries in each map from multiple threads.下面的代码应该从多个线程在每个映射中放置 2000 个条目。 But for the HashMap, there will be consistently fewer entries than 2000 in the map after the operation, since some of the puts will clash with each other and their result will be lost.但是对于 HashMap,操作后映射中的条目将始终少于 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<>());
    }
}

That's an interesting question.这是一个有趣的问题。

The correct answer is:正确答案是:

There are few realistic cases where which a sequence of get and put operations on a ConcurrentHashMap will produce the expected result in a multithreaded scenario.在多线程场景中, ConcurrentHashMap上的一系列 get 和 put 操作将产生预期结果的现实情况很少。 Instead of put() , you almost always need to use the atomic compare-and-mutate operations like computeIfAbsent() to do anything useful.代替put() ,您几乎总是需要使用像computeIfAbsent()这样的原子比较和变异操作来做任何有用的事情。 One exception is the case when you use the map as a cache and the possibility of having multiple threads compute the same entry is more efficient than blocking while one thread does it... but then do you really need a cache?一种例外情况是,当您将地图用作缓存并且让多个线程计算同一个条目的可能性比一个线程执行时阻塞的效率更高……但是您真的需要缓存吗? Not very often.不经常。

Just for the record, that would look like this:只是为了记录,这看起来像这样:

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; 

On the other hand, using a normal HashMap across two threads when one may be modifying the map while the other is also using it can lead to undefined behavior -- results not consistent with any sequence of operations, null pointer exceptions, or even a permanently corrupted data structure.另一方面,当一个线程可能正在修改映射而另一个线程也在使用它时,跨两个线程使用普通HashMap会导致未定义的行为——结果与任何操作序列不一致,空指针异常,甚至永久损坏的数据结构。

If I were asking this question in an interview, what I would be testing is: does the candidate understand that using thread-safe data structures doesn't make his algorithm thread-safe?如果我在面试中问这个问题,我要测试的是:应聘者是否理解使用线程安全的数据结构不会使他的算法成为线程安全的?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM