2010-04-11 112 views
4

這個問題既涉及C#和Java遍歷集合在兩個線程

如果您有沒有被修改的集合,該集合引用兩個線程,當你遍歷每個線程上發生的事情之間共享?

的ThreadA:Collection.iterator 的ThreadA:Collection.moveNext ThreadB:Collection.iterator ThreadB:Collection.moveNext

威爾threadB看到的第一個元素?

迭代器是否在請求時總是復位?如果這是交錯的,那麼會發生什麼情況,所以movenext和item是交錯的?有沒有處理所有元素的危險?

+0

在Java中使用BlockingQueue會更好。這是設計爲可以在任意數量的線程中共享的,並且可以在您閱讀時進行修改。 – 2010-04-11 09:16:01

+0

Op's Q簡而言之:「來自同一個集合的每個迭代器是否彼此獨立運行?」 – 2010-04-11 12:23:38

回答

3

它按預期工作,因爲每次請求迭代器時都會得到一個新的。

如果沒有,你將無法做foreach,然後對相同的集合進行foreach!

+0

它出於興趣如何做?你知道嗎 – 2010-04-11 08:07:41

+0

zihotki發佈了一些很好的鏈接。在C#中很容易看到它是如何工作的,只需將IEnumerable 添加到您的某個類中並要求它實現該接口 - 您會看到它添加了「public IEnumerator GetEnumerator()」,因此您需要提供一個實現IEnumerator - 現在製作其中一個,看看裏面有什麼。 GetEnumerator的每個請求都會獲得一個跟蹤枚舉的新對象。 – 2010-04-11 08:57:32

1

在Java中(我非常確定在C#中),標準API集合通常沒有單個迭代器。每次調用iterator()都會產生一個新的,它有自己的內部索引或指針,所以只要兩個線程都獲得自己的迭代器對象,就不會有問題。

但是,這不能保證接口,也沒有兩個迭代器沒有問題併發工作的能力。對於自定義集合的實現,所有投注都關閉。

2

按照慣例,實現了一個迭代器,以便遍歷操作永不改變集合的狀態。它只指向集合中的當前位置,並管理迭代邏輯。因此,如果你通過N個不同的線程掃描相同的集合,一切都應該正常工作。

但是請注意,Java的迭代器允許項目去除,並連的ListIterator支持設置操作。如果你至少想用其中一個線程來使用這些動作,你可能會遇到併發問題(ConcurrentModificationException),除非Iterator是專門爲這種場景設計的(比如使用ConcurrentHashMap的迭代器)。

0

至少在C#中,所有標準集合都可以在不同的線程上同時枚舉。然而,如果你在枚舉期間修改底層集合,任何線程上的枚舉都會炸掉(我們不相信任何編寫集合類的理智的開發者都會讓它的枚舉器以一種干擾枚舉的方式改變集合狀態,但這是可能的。但是,如果您使用的是標準集合,則可以放心地採用此方法,因此在同步集合訪問權限時使用像Single Writer/Multiple Reader這樣的鎖定策略。