Выбор ответа Middle Потоки и синхронизация обновлено
GetOrAdd в ConcurrentDictionary
Вопрос
Сколько раз может вызваться фабрика valueFactory при одновременных cache.GetOrAdd(key, k => Load(k)) из нескольких потоков?
Попробуйте сами
Выберите вариант, и откроется разбор.
Показать ответ и разбор
Коротко
Правильный ответ: Несколько раз, но в словарь попадёт только одно значение. ConcurrentDictionary не держит блокировку во время вызова фабрики, чтобы не блокировать других.
Варианты ответа
- Ровно один раз:
GetOrAddполностью атомарен вместе с фабрикой - Ни разу, если ключ уже был запрошен любым потоком хоть однажды
- Несколько раз, но в словарь попадёт только одно значениеправильный ответ
- Столько раз, сколько потоков, и все значения сохранятся по очереди
Разбор
ConcurrentDictionary не держит блокировку во время вызова фабрики, чтобы не блокировать других. Если ключа нет, несколько потоков могут одновременно вызвать Load, но сохранится один результат, и все получат его. Для дорогих фабрик используют Lazy<T>: GetOrAdd(key, k => new Lazy<V>(() => Load(k))).Value.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.