Какой объект лучше всего подходит для централизованного доступа к данным при множественном доступе из потоков с частым чтением и редкими модификациями
Что проверяют
Понимаете ли вы разницу между «одна блокировка на всех» и схемами, где читатели не мешают друг другу. Ожидаемый ответ ReaderWriterLockSlim, но сильный кандидат называет альтернативы и условия. Следом спрашивают, можно ли это использовать в асинхронном коде.
Как отвечать
Выбор зависит от того, как устроены данные:
ReaderWriterLockSlim: много читателей одновременно черезEnterReadLock(), писатель получает эксклюзивный доступ черезEnterWriteLock(). Нужен, когда меняется сложная структура и важны инварианты между её частями. РежимEnterUpgradeableReadLock()одновременно держит только один поток. СтарыйReaderWriterLockне используйте;- неизменяемый снимок с атомарной подменой: данные собираются в новый объект, ссылка заменяется через
Interlocked.ExchangeилиVolatile.Write, читатели работают вообще без блокировок. Для справочников и конфигурации часто лучший вариант, а с .NET 8 для снимка естьFrozenDictionary, оптимизированный под чтение; ConcurrentDictionary<TKey, TValue>: чтение без блокировок, запись с блокировкой отдельных сегментов. Хорош, если меняются отдельные ключи и не нужна согласованность между ними;ImmutableDictionaryсImmutableInterlocked: снимок без полного копирования при мелких обновлениях.
Про асинхронность: ReaderWriterLockSlim привязан к потоку, после await освобождать его может уже другой поток, и вы получите SynchronizationLockException. В асинхронном коде берут SemaphoreSlim или асинхронный reader/writer lock из сторонних библиотек.
Про цену: при очень коротких секциях обычный lock бывает быстрее, в .NET 9 для него появился тип System.Threading.Lock. Выбор подтверждают замером в BenchmarkDotNet.
Где спотыкаются
Считают ConcurrentDictionary универсальным ответом. Операция «проверить и добавить» из двух вызовов не атомарна, а фабрика в GetOrAdd может выполниться несколько раз.
Забывают try/finally вокруг EnterReadLock/ExitReadLock. Исключение оставляет блокировку захваченной, и писатели ждут вечно.
Отдают читателям изменяемую коллекцию из снимка. Если кто-то поменяет её на месте, схема без блокировок перестаёт быть безопасной.