我有一个静态内存缓存,每小时(或更长时间)写入一次,并且以极高的速率被许多线程读取。传统观点建议我遵循如下模式:
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);
}
}
}
最佳答案
当线程只从数据结构中读取时,您不需要锁。因此,由于写入非常罕见(而且,我假设,不是并发的),一个选项可能是制作字典的完整副本,对副本进行修改,然后以原子方式将旧字典与新字典交换:
public static class MyCache2
{
private static IDictionary<int, string> _cache;
static MyCache2()
{
_cache = new Dictionary<int, string>();
}
public static string GetData(int key)
{
string returnValue;
_cache.TryGetValue(key, out returnValue);
return returnValue;
}
public static void AddData(int key, string data)
{
IDictionary<int, string> clone = Clone(_cache);
if (!clone.ContainsKey(key))
clone.Add(key, data);
Interlocked.Exchange(ref _cache, clone);
}
}
关于c# - 高性能内存缓存的线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8195320/