简体   繁体   English

修改 ConcurrentHashMap 中的值

[英]Modifying values in ConcurrentHashMap

In ConcurrentHashMap there is concept of segmentation.在 ConcurrentHashMap 中有分段的概念。 What it means if two threads are trying to access ConcurrentHashMap they it gets divided in two blocks and default size of blocks is 16.这意味着如果两个线程试图访问 ConcurrentHashMap,它们会被分成两个块,块的默认大小为 16。

Now suppose in a scenario where ConcurrentHashMap has only two elements and two different threads comes and thread1 tries to modify first value and thread2 tries to modify second value.现在假设在 ConcurrentHashMap 只有两个元素和两个不同的线程的情况下,线程 1 尝试修改第一个值,线程 2 尝试修改第二个值。 In this case whether ConcurrentHashMap will go for segmentation?在这种情况下,ConcurrentHashMap 是否会进行分段?

Now in a different scenario both the threads try to modify same value how ConcurrentHashMap will handle this situation?现在在不同的场景中,两个线程都尝试修改相同的值 ConcurrentHashMap 将如何处理这种情况? By using locking mechanism or is there something else ?通过使用锁定机制还是有别的什么?

ConcurrentHashMap has several buckets. ConcurrentHashMap 有几个桶。 Keys are mapped, based on their hash value, into one of the buckets.键根据其散列值映射到其中一个桶中。 When you add or retrieve a value, the bucket associated with that key is locked.当您添加或检索一个值时,与该键关联的存储桶将被锁定。

In the case of your first question, there are two possibilities: either both keys live in the same bucket, or they live in different buckets.在您的第一个问题的情况下,有两种可能性:两个键都位于同一个存储桶中,或者它们位于不同的存储桶中。 In the first case, only one thread can work at a time -- the first one to acquire the lock will grab it and work, the second thread will wait its turn.在第一种情况下,一次只有一个线程可以工作——第一个获取锁的线程将获取锁并工作,第二个线程将等待轮到它。 In the second case, where the keys are in different buckets, they'll each acquire independent locks and do their work concurrently.在第二种情况下,密钥位于不同的存储桶中,它们每个都将获得独立的锁并同时执行它们的工作。

For your second question, it is the bucket that gets locked, and nothing else.对于你的第二个问题,是被锁定了,没有别的。 If two threads try to store two values for the same key, then ConcurrentHashMap promises that one of the two values will be associated with the key.如果两个线程尝试为同一个键存储两个值,则 ConcurrentHashMap 承诺两个值之一将与键相关联。 ie if thread A runs map.put("Answers",2);如果线程 A 运行map.put("Answers",2); and thread B runs map.put("Answers",10);线程 B 运行map.put("Answers",10); , then ConcurrentHashMap will ensure that the map is valid and contains either 2 or 10 for "Answers" , but it won't make any promises about which of those two it is. ,然后 ConcurrentHashMap 将确保映射是有效的,并且包含210"Answers" ,但它不会对这两个中的哪一个做出任何承诺。

CHM guarantees that those operations (eg put , putIfAbsent , etc.) won't overlap, and yes, that's done with locking. CHM 保证这些操作(例如putputIfAbsent等)不会重叠,是的,这是通过锁定完成的。 Each segment of the CHM has its own lock that gets taken whenever you're modifying that segment. CHM 的每个段都有自己的锁,每当您修改该段时都会使用该锁。

(For reference, as @Affe pointed out, if you're modifying the contents of a value in the ConcurrentHashMap , CHM doesn't do -- can't do -- anything to make that thread safe.) (作为参考,正如@Affe 指出的那样,如果您正在修改ConcurrentHashMap中某个值的内容,则 CHM 不会做 - 不能做 - 任何使该线程安全的事情。)

First of all , new implementation of CHM doesn't use Segments at all, it still uses array of nodes, if node in given index doesn't exist and two threads are trying to insert two entries with hashcode that equals to given index then CHM uses CAS , otherwise if node exists then CHM uses lock on the first element of this node to put new value.首先,新的 CHM 实现根本不使用 Segments,它仍然使用节点数组,如果给定索引中的节点不存在并且两个线程试图插入两个具有等于给定索引的哈希码的条目,则 CHM使用 CAS ,否则如果节点存在,则 CHM 使用锁定该节点的第一个元素来放置新值。 Reads in CHM are non blocking and use happen before guarantee with the help of atomic reads from Unsafe class. CHM 中的读取是非阻塞的,并且在 Unsafe 类的原子读取的帮助下,使用发生在保证之前。 Check out my blog about CHM for more details https://strogiyotec.github.io/pages/posts/chm.html查看我关于 CHM 的博客了解更多详情https://strogiyotec.github.io/pages/posts/chm.html

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

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