У меня есть статический кэш в памяти, который записывается только один раз в час ( или более ), а читается многими потоками с чрезвычайно высокой скоростью . Обычная мудрость предполагает, что я следую примеру, подобному следующему:
public static class MyCache
{
private static IDictionary<int, string> _cache;
private static ReaderWriterLockSlim _sharedLock;
static MyCache()
{
_cache = new Dictionary<int, string>();
_sharedLock = new ReaderWriterLockSlim();
}
public static string GetData(int key)
{
_sharedLock.EnterReadLock();
try
{
string returnValue;
_cache.TryGetValue(key, out returnValue);
return returnValue;
}
finally
{
_sharedLock.ExitReadLock();
}
}
public static void AddData(int key, string data)
{
_sharedLock.EnterWriteLock();
try
{
if (!_cache.ContainsKey(key))
_cache.Add(key, data);
}
finally
{
_sharedLock.ExitWriteLock();
}
}
}
Как упражнение в микрооптимизации, как я могу сбить еще больше тиков в относительной стоимости общих чтения блокировок? Время записи может быть дорогим, так как это случается редко. Мне нужно сделать чтение как можно быстрее. Могу ли я просто снять блокировки read (ниже) и остаться поточно-ориентированным в этом сценарии? Или есть версия без блокировки , которую я могу использовать? Я знаком с защитой памяти, но не знаю, как безопасно применять ее в этом случае.
Примечание: я не привязан ни к одному шаблону, поэтому любые предложения приветствуются, если конечный результат быстрее и в C # 4.x. *
public static class MyCache2
{
private static IDictionary<int, string> _cache;
private static object _fullLock;
static MyCache2()
{
_cache = new Dictionary<int, string>();
_fullLock = new object();
}
public static string GetData(int key)
{
//Note: There is no locking here... Is that ok?
string returnValue;
_cache.TryGetValue(key, out returnValue);
return returnValue;
}
public static void AddData(int key, string data)
{
lock (_fullLock)
{
if (!_cache.ContainsKey(key))
_cache.Add(key, data);
}
}
}