Если этот словарь редко пишется и часто читается, то я часто использую безопасную двойную блокировку, заменяя весь словарь при записи. Это особенно эффективно, если вы можете выполнять групповые записи вместе, чтобы сделать их менее частыми.
Например, это урезанная версия метода, который мы используем, который пытается получить объект схемы, связанный с типом, и если он не может, то он идет вперед и создает объекты схемы для всех найденных типов в той же сборке, что и указанный тип, чтобы минимизировать количество копий всего словаря:
public static Schema GetSchema(Type type)
{
if (_schemaLookup.TryGetValue(type, out Schema schema))
return schema;
lock (_syncRoot) {
if (_schemaLookup.TryGetValue(type, out schema))
return schema;
var newLookup = new Dictionary<Type, Schema>(_schemaLookup);
foreach (var t in type.Assembly.GetTypes()) {
var newSchema = new Schema(t);
newLookup.Add(t, newSchema);
}
_schemaLookup = newLookup;
return _schemaLookup[type];
}
}
Таким образом, словарь в этом случае будет перестраиваться, самое большее, столько раз, сколько существует сборок с типами, которые нуждаются в схемах. До конца срока службы приложения доступ к словарю будет свободен от блокировки. Копия словаря становится единовременной стоимостью инициализации сборки. Подстановка словаря является поточно-ориентированной, поскольку записи указателей являются атомарными, поэтому вся ссылка переключается сразу.
Вы можете применять аналогичные принципы и в других ситуациях.