2013-04-25 98 views
1

我正在閱讀有關哈希表的問題,這個問題讓我感到震驚。哈希表是同步的,所以Hashtable中的迭代器是否可以進行故障安全?哈希表中的併發和故障安全行爲

此外,對於故障安全集合,當多個線程嘗試訪問集合時,您將不會收到ConcurrentModificationException,因爲每個線程都在自己的副本上工作。我想知道這是否意味着每個線程的內存中都創建了Collection的實際物理副本?

+0

請養成添加相關語言標籤的習慣。 – 2013-04-25 02:37:04

+0

當然,對不起。 – Setafire 2013-04-25 02:41:37

+0

只是澄清,ConcurrentModificationException(儘管它的名稱)_really與threads_無關。線程安全和「修改安全期間的迭代」(CME)是兩個正交的概念。 – jtahlborn 2013-04-25 03:35:04

回答

2

嗯......如果「故障安全」你的意思是你不能得到一個ConcurrentModificationException,那麼那麼答案是否定的,您可以你就可以使用Iterator得到一個Hashtable該異常。 javadoc明確指出。


此外,對於故障安全的集合,當多個線程試圖訪問一個集合,你會不會因爲每個線程正在其自身的副本,它得到一個ConcurrentModificationException的。

(你似乎引用或總結,從地方。無論如何,我不認爲這是正確的。)

我不知道這是否意味着,這的一個實際的物理拷貝集合是在每個線程的內存中創建的?

在某些情況下,迭代器正在處理一個不會被修改的副本。在其他情況下,迭代器正在處理可能會被修改和/或根本不代表集合的一致快照的事情。這實際上取決於如何爲您正在討論的特定集合類指定「故障安全」行爲。 (和對集合類的好東西之一是,他們明確規定,你可以和不可以靠的是什麼。你只需要仔細閱讀說明書以確保你真正瞭解他們!)


哦,所以Hashtable中的迭代器是快速失敗的,但枚舉器是自動防故障的。

第一部分是正確的。第二個是不正確的。

Hashtable返回的Enumeration對象不保證是故障安全的。 javadocs的狀態是Enumeration不是快速故障。當您修改Hashtable並同時枚舉它時實際發生的是未指定。 (如果您真的想知道,請查看您正在使用的特定Java版本的源代碼。)

+0

哦,所以Hashtable中的迭代器快速失敗,但枚舉器是安全的。感謝那。 – Setafire 2013-04-25 02:47:29

+0

是的,我在Java博客中讀到。但是你的回答讓我更加好奇。那麼,集合的故障安全行爲如何實際執行? – Setafire 2013-04-25 02:57:52

+0

@Setafire - 就像我說的。這取決於指定的行爲實際上是什麼!沒有單一的答案。 – 2013-04-25 02:59:21

0

RTFM:

由所有此類的「collection視圖方法」返回的collection的iterator方法返回的迭代器是快速失敗的:如果Hashtable是在任何時間後的結構修飾除了通過迭代器自己的remove方法以外,任何方式都會創建迭代器,迭代器將拋出ConcurrentModificationException異常。因此,面對併發修改,迭代器快速而乾淨地失敗,而不是在將來某個未確定的時間冒着任意的,非確定性的行爲風險。 Hashtable的鍵和元素方法返回的枚舉不是快速失敗的。

請注意,迭代器的故障快速行爲無法得到保證,因爲一般來說,在出現非同步併發修改時不可能做出任何硬性保證。失敗快速迭代器盡最大努力拋出ConcurrentModificationException。因此,編寫一個依賴於此異常的程序是正確的:迭代器的快速失敗行爲應僅用於檢測錯誤。

換句話說,迭代通過Hashtable不大於迭代過非同步HashMap更安全。