Потокобезопасность доступа к списку <> объектов только для чтения - PullRequest
1 голос
/ 17 декабря 2010

У меня есть список объектов, которые будут доступны многим объектам во многих потоках.Для обеспечения безопасности потока я создал список и его объект только для чтения.Моя единственная проблема - итераторы объекта List<>, потому что я помню, как читал кое-что о проблемах безопасности потоков итераторов.У меня есть проблема?

alt text

Для пояснения: в классе BarObservable строка List < Bar > доступна только для чтения.Отдельные строки списка также доступны только для чтения.Класс MarketDataAdaptor использует BarService для добавления новых баров в класс BarsObservable.На диаграмме это не показано, но IBarObservers передается ссылка на List < Bar >.Они не могут писать в него, но они используют итератор списка.Между тем, последний бар обновляется, и после его завершения новый бар добавляется в конец списка.

1 Ответ

2 голосов
/ 17 декабря 2010

Насколько я понимаю, вы в настоящее время предоставляете две гарантии неизменности:

  1. Существует неизменная ссылка (и) на List<Bar> объект.
  2. Сам тип Bar является неизменным или, по договоренности, его экземпляры не видоизменяются после добавления в список.

Ничего из этого не достаточно, чтобы справиться с любыми параллельными сценариями чтения / записи, поскольку сам List<T> тип не является поточно-ориентированным.

  1. Если у вас несколько несинхронизированных писателей, вы можете испортить список.
  2. Если у вас есть один писатель с читателями в других потоках, вы, вероятно, не повредите список. С другой стороны, читатели не будут работать правильно. Если вам повезет, повторение списка в середине записи вызовет исключение «Коллекция изменена во время перечисления». Если нет, ваша программа молча потеряет свою функциональную корректность.

Теперь вы можете попробовать синхронизировать доступ к списку с блокировками, ReaderWriterLockSlims и т. Д. То, как вы это сделаете, будет специфичным для отношений производитель / потребитель в вашей конкретной ситуации. Например, вы можете заблокировать мутацию во время перечисления одним из следующих способов:

  1. Задержать попытку видоизменения до тех пор, пока существует активный нераспределенный перечислитель.
  2. Каждый раз, когда запрашивается перечислитель, пишите блок. Скопируйте список в другой список; верните его перечислитель, а затем разблокируйте авторов.

Но я бы посоветовал, если вы работаете в .NET 4.0, взглянуть на классы поточно-ориентированных коллекций в пространстве имен System.Collections.Concurrent. В частности, вы можете найти класс BlockingCollection<T> именно тем, что вам нужно.

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

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