2010-04-11 4 views
4

Этот вопрос относится как к C# и JavaИтерация Коллекция В двух нитях

Если у вас есть коллекция, которая не модифицируется и что ссылка коллекции разделена между двумя нитями, что происходит, когда вы итерацию по каждой теме ??

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

Will threadB увидеть первый элемент?

Является ли итератор всегда сбрасываться, когда его запрашивают? Что произойдет, если это чередуется, поэтому movenext и элемент чередуются? Есть ли опасность, что вы не обрабатываете все элементы?

+0

Вам гораздо лучше использовать BlockingQueue в Java. Он предназначен для совместного использования по любому количеству потоков и может быть изменен во время чтения. –

+0

Op's Q в двух словах: «Каждый литератор из одной коллекции действует независимо друг от друга?» –

ответ

3

Работает должным образом, потому что каждый раз, когда вы запрашиваете итератор, вы получаете новый.

Если бы вы этого не сделали, вы не смогли бы сделать foreach, а затем foreach в той же коллекции!

+0

Как это сделать из интереса? Знаете ли вы, что –

+0

zihotki разместили хорошие ссылки.В C# легко увидеть, как это работает, просто добавьте IEnumerable в один из ваших классов и попросите его реализовать интерфейс - вы увидите, что он добавляет «public IEnumerator GetEnumerator()», поэтому вам нужно предоставить объект, который реализует IEnumerator - так что теперь сделайте один из них и посмотрите, что в нем. Каждый запрос GetEnumerator получает новый объект, который отслеживает перечисление. –

1

В Java (и я также уверен, что на C#), стандартные коллекции API обычно не имеют одного итератора. Каждый вызов iterator() создает новый, который имеет свой собственный внутренний указатель или указатель, так что до тех пор, пока оба потока получат собственный объект итератора, проблем не должно быть.

Однако это не гарантируется интерфейсом, а также невозможность одновременной работы двух итераторов без проблем. Для пользовательских реализаций коллекций все ставки отключены.

2

По соглашению, Итератор реализован так, что действие обхода никогда не изменяет состояние коллекции. Он указывает только на текущую позицию в коллекции и управляет логикой итерации. Поэтому, если вы сканируете одну и ту же коллекцию на N разных потоков, все должно работать нормально.

Однако, обратите внимание, что итератор Java позволяет удаления элементов и ListIterator даже поддерживает набор операцию. Если вы хотите использовать эти действия хотя бы одним из потоков, вы, вероятно, столкнетесь с проблемами параллелизма (ConcurrentModificationException), если Итератор специально не предназначен для таких сценариев (например, с помощью итераторов ConcurrentHashMap).

0

По крайней мере, на C# все стандартные коллекции могут быть перечислены одновременно на разных потоках. Тем не менее, перечисление на любой поток взорвется, если вы измените базовую коллекцию во время перечисления (как и должно быть.) Я не верю, что любой здравомыслящий разработчик, создающий класс коллекции, будет иметь свои счетчики, мутирующие состояние коллекции таким образом, который мешает перечислению , но это возможно. Однако, если вы используете стандартную коллекцию, вы можете смело предположить это и, следовательно, использовать стратегии блокировки, такие как Single Writer/Multiple Reader, при синхронизации доступа к коллекции.

Смежные вопросы