Java 理解concurrentHashMap

Java 理解concurrentHashMap,java,multithreading,dictionary,Java,Multithreading,Dictionary,众所周知,该类允许我们安全地使用迭代器。据我从Map的来源了解,它是通过将当前Map状态存储到迭代器本身来实现的。下面是表示迭代器的内部类(在调用iterator()时创建了一个子类): 抽象类哈希迭代器{ int-nextSegmentIndex; int-nextTableIndex; HashEntry[]当前表; HashEntry nextEntry; HashEntry返回; //方法与方法 } 但是,如果某个线程在构造迭代器的过程中向映射写入了某些内容,该怎么办?那么我们能得到地

众所周知,该类允许我们安全地使用迭代器。据我从
Map
的来源了解,它是通过将当前
Map
状态存储到迭代器本身来实现的。下面是表示迭代器的内部类(在调用
iterator()
时创建了一个子类):

抽象类哈希迭代器{
int-nextSegmentIndex;
int-nextTableIndex;
HashEntry[]当前表;
HashEntry nextEntry;
HashEntry返回;
//方法与方法
}
但是,如果某个线程在构造迭代器的过程中向映射写入了某些内容,该怎么办?那么我们能得到地图的非确定性状态吗


问题是映射的两种方法都不同步。对于
put
方法,有一个
ReentrantLock
,但就是它(据我所知)。因此,我不明白迭代器如何支持正确的状态,即使某些线程在其构造期间写入映射

迭代器提供弱一致性状态。它不提供数据的事务视图。它只允许您在未更改的情况下看到所有键/值,如果更改了,您可能会看到,也可能不会看到,但不会出现错误。

迭代器提供弱一致性状态。它不提供数据的事务视图。它只允许您在未更改的情况下看到所有键/值,如果更改了,您可能会看到,也可能看不到,但不会出现错误。

来自
ConcurrentHashMap
的java:

检索操作(包括get)通常不会阻塞,因此 与更新操作重叠(包括放置和删除)。检索 反映最近完成的更新操作的结果 坚持他们的开始。用于聚合操作,如putAll和 清除、并发检索可能只反映插入或删除 一些条目。类似地,迭代器和枚举返回元素 反映哈希表在 创建迭代器/枚举。他们不会扔东西 ConcurrentModificationException但是,迭代器的设计目的是 一次只能由一个线程使用。

现在回答问题

但是,如果某个线程在运行期间向映射写入了某些内容,该怎么办 迭代器的构造

如前所述,迭代器表示某个时间点的状态。因此,这可能不是最近的一个州

迭代器如何支持正确的状态,即使某些线程 在地图构建期间写入地图

保证的是,如果在迭代过程中放置/移除,则不会出现问题。但是,不能保证一个线程将看到另一个线程执行的映射更改(不从映射中获取新的迭代器)。迭代器保证在创建时反映映射的状态。进一步的更改可能会反映在迭代器中,但它们不必反映在迭代器中。

来自java of
ConcurrentHashMap

检索操作(包括get)通常不会阻塞,因此 与更新操作重叠(包括放置和删除)。检索 反映最近完成的更新操作的结果 坚持他们的开始。用于聚合操作,如putAll和 清除、并发检索可能只反映插入或删除 一些条目。类似地,迭代器和枚举返回元素 反映哈希表在 创建迭代器/枚举。他们不会扔东西 ConcurrentModificationException但是,迭代器的设计目的是 一次只能由一个线程使用。

现在回答问题

但是,如果某个线程在运行期间向映射写入了某些内容,该怎么办 迭代器的构造

如前所述,迭代器表示某个时间点的状态。因此,这可能不是最近的一个州

迭代器如何支持正确的状态,即使某些线程 在地图构建期间写入地图


保证的是,如果在迭代过程中放置/移除,则不会出现问题。但是,不能保证一个线程将看到另一个线程执行的映射更改(不从映射中获取新的迭代器)。迭代器保证在创建时反映映射的状态。进一步的更改可能会反映在迭代器中,但它们不一定会反映出来。

这是否意味着如果我们不确定迭代器构建过程中其他线程的修改情况,您建议不要使用映射?@St.Antario我建议您使用它,除非,您关心迭代时发生的更改。这是否意味着,如果我们不确定迭代器构造期间其他线程是否进行了修改,您建议不要使用映射?@St.Antario我建议您使用它,除非您关心迭代时发生的更改。但是,不能保证一个线程会看到另一个线程在当前实现中对映射所做的更改,我想说它不会看到这些更改。…。@St.Antario:是的,如果使用两个线程来迭代同一个CHM,那么它们将在各自创建迭代器时所看到的副本上进行迭代。明白了,非常感谢。因此,该规则也适用于在构造迭代器时并发写入映射,对吗?但是,不能保证一个线程会看到另一个线程在当前实现中对映射执行的更改,我想说,它不会看到它们。…。@St.Antario:是的,如果使用两个线程来迭代同一个CHM,那么它们将在各自创建迭代器时看到的副本上进行迭代。明白了,谢谢。因此,该规则也适用于
abstract class HashIterator {
        int nextSegmentIndex;
        int nextTableIndex;
        HashEntry<K,V>[] currentTable;
        HashEntry<K, V> nextEntry;
        HashEntry<K, V> lastReturned;

        //Methods and ctor
}