У меня есть класс, используемый для кэширования доступа к ресурсу базы данных. Это выглядит примерно так:
//gets registered as a singleton
class DataCacher<T>
{
IDictionary<string, T> items = GetDataFromDb();
//Get is called all the time from zillions of threads
internal T Get(string key)
{
return items[key];
}
IDictionary<string, T> GetDataFromDb() { ...expensive slow SQL access... }
//this gets called every 5 minutes
internal void Reset()
{
items.Clear();
}
}
Я несколько упростил этот код, но суть в том, что существует потенциальная проблема параллелизма, заключающаяся в том, что при очистке элементов, если вызывается метод Get, все может пойти не так.
Теперь я могу просто добавить блокировку блоков в Get и Reset, но я обеспокоен тем, что блокировки в Get снизят производительность сайта, так как Get вызывается каждым потоком запросов в веб-приложении много раз.
Я могу сделать что-то с дважды проверенными блокировками, я думаю, но я подозреваю, что есть более чистый способ сделать это, используя что-то более умное, чем блок lock {}. Что делать?
edit: Извините, я не делал этого раньше, но реализация items.Clear (), которую я использую, на самом деле не является прямым словарем. Это оболочка ResourceProvider, которая требует, чтобы реализация словаря вызывала .ReleaseAllResources () для каждого из элементов по мере их удаления. Это означает, что вызывающий код не хочет работать со старой версией, которая находится в процессе утилизации. Учитывая это, метод Interlocked.Exchange является правильным?