Блокировка HttpRuntime.Cache для отложенной загрузки

У нас есть веб-сайт, на котором работает .NET 2.0, и мы начали использовать ASP.Net HttpRuntime.Cache для хранения результатов частого поиска данных, чтобы сократить доступ к нашей базе данных.

Фрагмент:

 
lock (locker)
{
    if (HttpRuntime.Cache[cacheKey] == null)
    {
        HttpRuntime.Cache.Insert(cacheKey, GetSomeDataToCache(), null, DateTime.Today.AddDays(1), Cache.NoSlidingExpiration);       
    }
    return ((SomeData)HttpRuntime.Cache[cacheKey]).Copy();
}

Мы пессимистично блокируемся всякий раз, когда хотим посмотреть кеш. Тем не менее, я видел различные блоги, опубликованные в Интернете, в которых предлагалось выполнить блокировку после проверки значения кеша, чтобы избежать накладных расходов на блокировку. Это не кажется правильным, поскольку после проверки в кеш мог быть записан другой поток.

Итак, наконец, мой вопрос: каков «правильный» способ сделать это? Используем ли мы даже правильный объект синхронизации потоков? Мне известно о ReaderWriterLockSlim (), но мы используем .NET 2.0.


person Jason Slocomb    schedule 15.01.2009    source источник


Ответы (4)


Насколько мне известно, объект Cache является потокобезопасным, поэтому вам не понадобится блокировка.

person Darin Dimitrov    schedule 15.01.2009

Объект Cache в .NET является потокобезопасным, поэтому блокировка не требуется. Ссылка: http://msdn.microsoft.com/en-us/library/system.web.caching.cache.aspx.

person mkchandler    schedule 15.01.2009
comment
Тот факт, что объект Cache не будет разрушен при многопоточном доступе, не означает, что неатомарная проверка, если что-то кэшируется, добавляет это, если это не последовательность, не требует какой-либо защиты. - person Will Dean; 04.01.2012

Ваш код, вероятно, заставляет вас думать, что этот элемент будет кэширован в течение 1 дня, и ваша последняя строка всегда будет предоставлять вам эти данные, но это не так. Как говорили другие, операции с кешем синхронизируются, поэтому вам не следует блокироваться в этот момент.

Посмотрите здесь правильный способ сделать это.

person user134706    schedule 11.07.2009

Потокобезопасность. Означает ли это, что все остальные процессы ждут, когда закончится ваш код?

Потокобезопасность - вы можете быть уверены, что полученный вами элемент не будет «разрезан пополам» или частично уничтожен обновлением кеша в то же время, когда вы читаете этот элемент.

item = cache.Get(key);

Но что бы вы ни делали после этого - другой поток может работать с кешем (или любым другим общим ресурсом). Если вы хотите что-то сделать с кешем на основе того, что ваш извлеченный элемент имеет значение null или нет, я не был бы на 100% уверен, что он еще не исправлен другим экземпляром вашего собственного кода, являющимся несколькими инструкциями ЦП вперед, обслуживающими другого читателя на той же странице вашего онлайн-журнала по двигателям.

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

person tofo    schedule 23.05.2015