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