В ASP.NET MVC у нас есть несколько экземпляров данных, для построения которых требуется много ресурсов и времени. Мы хотим их кэшировать.
MemoryCache
обеспечивает определенный уровень потокобезопасности, но недостаточный, чтобы избежать параллельного запуска нескольких экземпляров кода сборки. Вот пример:
var data = cache["key"];
if(data == null)
{
data = buildDataUsingGoodAmountOfResources();
cache["key"] = data;
}
Как вы можете видеть, на загруженном веб-сайте сотни потоков могут выполняться внутри оператора if одновременно, пока данные не будут построены, что сделает операцию построения еще медленнее, излишне потребляя ресурсы сервера.
Существует атомарная реализация AddOrGetExisting
в MemoryCache, но она неправильно требует «устанавливаемого значения» вместо «кода для извлечения устанавливаемого значения», что, по моему мнению, делает данный метод почти полностью бесполезным.
Мы использовали нашу собственную специальную структуру вокруг MemoryCache, чтобы сделать это правильно, однако для этого требуются явные блокировки
s. Использование объектов блокировки для каждой записи обременительно, и мы обычно избавляемся от совместного использования объектов блокировки, что далеко от идеала. Это навело меня на мысль, что причины избегать такого соглашения могут быть преднамеренными.
Итак, у меня есть два вопроса:
Не лучше ли не блокировать
строительный код? (Интересно, это могло бы оказаться более чувствительным для одного)
Каков правильный способ добиться блокировки каждой записи для MemoryCache для такой блокировки? Сильное желание использовать строку key
в качестве объекта блокировки отклоняется в «блокировке .NET 101».