java – 关于并发hashmap的内部工作

我正在浏览ConcurrentHashMap和
this related tutorial,并提出了一些问题.

>在文章中,提到ConcurrentHashMap允许多个读取器同时读取而不受任何阻塞.这是通过基于并发级别将Map划分为不同的部分并在更新期间仅锁定Map的一部分来实现的.默认并发级别为16,因此Map分为16个部分,每个部分由不同的锁控制.这意味着,16个线程可以同时在Map上运行,直到它们在Map的不同部分上运行.这使得ConcurrentHashMap具有高性能,尽管保持线程安全完整.但是,它有一个警告:由于put(),remove(),putAll()或clear()等更新操作不同步,因此并发检索可能无法反映Map上的最新更改
>文章中还提到了另一点:要记住的另一个要点是迭代CHM,keySet返回的迭代器是弱一致的,它们只反映某一点的ConcurrentHashMap状态,可能不反映任何最近的更改.

我没有理解以粗体突出显示的要点,您能提供更多信息或在简单的程序中向我展示吗?

最佳答案 >

Since update operations like put(), remove(), putAll() or clear() is not synchronized, concurrent retrieval may not reflect most recent change on Map

据我了解,这意味着在一个线程中修改地图可能不一定会被另一个线程中同时发生的检索所看到.请考虑以下示例:

                  Thread 1 starts              Thread 1's call to get("a")
                 a call to get("a")             completes, returning null
                         |                                 |
Thread 1        ---------+---------------------------------+-------
                             time ----->
Thread 2        -----+---------------------------+-----------------
                     |                           |
             Thread 2 starts a            Thread 2's call to
            call to put("a", 1)          put("a", 1) completes

即使线程2在地图中放置一个值,线程1的执行完成,但线程1没有“看到”地图修改,并返回null.
>

Another important point to remember is iteration over CHM, Iterator returned by keySet of ConcurrentHashMap are weekly consistent and they only reflect state of ConcurrentHashMap and certain point and may not reflect any recent change.

这是类似的情况.如果线程1从ConcurrentHashMap的keySet获得Iterator,并且稍后线程2在映射中放入新条目,则不保证线程1的迭代器看到该条目. (它可能会也可能不会.)

点赞