我正在阅读有关 Hashtables 的内容,这个问题让我印象深刻。哈希表是同步的,那么哈希表上的迭代器是否安全?
此外,对于故障安全集合,当多个线程尝试访问一个集合时,您不会收到 ConcurrentModificationException,因为每个线程都在处理它自己的副本。我想知道这是否意味着在内存中为每个线程创建了 Collection 的实际物理副本?
我正在阅读有关 Hashtables 的内容,这个问题让我印象深刻。哈希表是同步的,那么哈希表上的迭代器是否安全?
此外,对于故障安全集合,当多个线程尝试访问一个集合时,您不会收到 ConcurrentModificationException,因为每个线程都在处理它自己的副本。我想知道这是否意味着在内存中为每个线程创建了 Collection 的实际物理副本?
嗯...如果“故障安全”是指您无法获得 a ConcurrentModificationException
,那么答案是否定的。您可以Hashtable
在 a 上使用 a 时获得该异常Iterator
。javadoc明确说明了这一点。
此外,对于故障安全集合,当多个线程尝试访问一个集合时,您不会收到 ConcurrentModificationException,因为每个线程都在处理它自己的副本。
(您似乎从某个地方引用或总结了这一点。无论如何,我认为它不准确。)
我想知道这是否意味着在内存中为每个线程创建了 Collection 的实际物理副本?
在某些情况下,迭代器正在处理一个不会被修改的副本。在其他情况下,迭代器正在处理一些可以修改和/或根本不代表集合的一致快照的东西。这实际上取决于如何为您正在谈论的特定集合类指定“故障安全”行为。(关于集合类的好处之一是它们清楚地指定了您可以依赖和不能依赖的内容。您只需要仔细阅读规范以确保您真正理解它们!!)
哦,所以 Hashtable 中的迭代器是故障快速的,但枚举器是故障安全的。
第一部分是正确的。第二个是不正确的。
不保证Enumeration
返回的对象是故障安全的。javadocsHashtable
的状态是它们不是快速失败的。未指定修改 a并同时枚举它时实际发生的情况。(如果您真的想知道,请查看您正在使用的特定 Java 版本的源代码。)Enumeration
Hashtable
实时调频:
由此类的所有“集合视图方法”返回的集合的迭代器方法返回的迭代器是快速失败的:如果在创建迭代器后的任何时间对 Hashtable 进行结构修改,除了通过迭代器自己的删除之外的任何方式方法,迭代器将抛出 ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒任意的、非确定性的行为。Hashtable 的键和元素方法返回的枚举不是快速失败的。
请注意,不能保证迭代器的快速失败行为,因为一般来说,在存在不同步的并发修改的情况下,不可能做出任何硬保证。快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖于这个异常的正确性的程序是错误的:迭代器的快速失败行为应该只用于检测错误。
换句话说,对 a 的迭代Hashtable
并不比对 unsynchronized 的迭代更安全HashMap
。
Hashtable<String, Integer> hashtable = new Hashtable<>();
Integer a = hashtable.put("a", 1);
Integer a1 = hashtable.put("b", 2);
Integer a3 = hashtable.put("c", 3);
Iterator<Map.Entry<String, Integer>> iterator = hashtable.entrySet().iterator();
while(iterator.hasNext()){
hashtable.put("d",4);
iterator.next();
}