Почему SynchronizedCollection <T>не блокируется на IEnumerable.GetEnumerator () - PullRequest
5 голосов
/ 17 декабря 2009

Почему SynchronizedCollection<T> не получает блокировку SyncObj в явной реализации IEnumerable.GetEnumerator()

  IEnumerator IEnumerable.GetEnumerator()
    {
        return this.items.GetEnumerator();
    }

Неявная реализация получает блокировку SyncOb (проверяется отражателем).

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

Ответы [ 3 ]

4 голосов
/ 17 декабря 2009

Потому что у класса нет возможности узнать, когда код клиента выполнен с использованием итератора. Это одна из причин, по которой документы библиотеки MSDN на классы System.Collection всегда предупреждают, что повторение коллекции не является потокобезопасным.

Хотя они, похоже, забыли упомянуть об этом в статье для SynchronizedCollection. Ирония ...

1 голос
/ 17 декабря 2009

Я собираюсь пойти дальше и сказать, что это может быть ошибкой ( ed: или, по крайней мере, несоответствие ) в реализации. Reflector показывает именно то, что вы видите, что любая другая явная реализация вызывает блокировку для данного SyncRoot, за исключением IEnumerable.GetEnumerator().

Возможно, вам следует отправить заявку на Microsoft Connect .

Я считаю, что причина, по которой неявный метод GetEnumerator() вызывает lock, заключается в том, что List<T>.GetEnumerator() создает новый Enumerator<T>, который опирается на приватное поле _version в списке. Хотя я согласен с другими авторами, что я не вижу смысла в блокировке вызова GetEnumerator(), но, поскольку конструктор Enumerator<T> опирается на не поточнобезопасные поля, имеет смысл блокировать. Или, по крайней мере, оставаться в согласии с неявными реализациями.

1 голос
/ 17 декабря 2009

Изменение коллекции, когда кто-то использует итератор, в любом случае является нарушением параллелизма.

Какой была бы ваша альтернатива? Заблокировать коллекцию при получении итератора и не разблокировать ее до тех пор, пока итератор не будет уничтожен?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...