RPM*_*984 3 c# asp.net-mvc caching .net-4.0 thread-safety
场景:
List<T>不是线程安全的.我已阅读ConcurrentBag<T>和ConcurrentDictionary<T>,但不知道我是否应该用其中的一个,或实现同步/锁定自己.
我在.NET 4上,所以我正在使用它ObjectCache作为单例实例MemoryCache.Default.我有一个服务层,它与缓存一起工作,服务接受一个实例ObjectCache,它通过构造函数DI完成.这样,所有服务共享同一个ObjectCache实例.
主要的线程安全问题是我需要遍历当前的"缓存"集合,如果我正在使用的孩子已经在那里,我需要删除它并添加我正在使用的那个,这个枚举是导致问题的原因.
有什么建议?
是的,要有效地实现缓存,它需要快速查找机制,因此List<T>开箱即用的数据结构错误.A Dictionary<TKey, TValue>是缓存的理想数据结构,因为它提供了一种替换方法:
var value = instance.GetValueExpensive(key);
Run Code Online (Sandbox Code Playgroud)
有:
var value = instance.GetValueCached(key);
Run Code Online (Sandbox Code Playgroud)
通过在字典中使用缓存值并使用字典来执行繁重的查找.来电者不是明智之举.
但是,如果调用者可以从多个线程调用,那么.NET4提供ConcurrentDictionary<TKey, TValue>了在这种情况下完美的工作.但字典缓存了什么?在您的情况下,字典键似乎是子项,字典值是该子项的数据库结果.
好了,现在我们有了一个线程安全且高效的数据库结果缓存,由孩子键入.我们应该为数据库结果使用什么数据结构?
你还没有说出这些结果是什么样的,但是既然你使用LINQ,我们知道它们至少IEnumerable<T>也许甚至可能List<T>.所以我们回到了同样的问题,对吧?因为List<T>不是线程安全的,所以我们不能将它用于字典值.或者我们可以吗?
缓存必须是来自调用者的视点的只读.你说LINQ你做"添加/删除"的东西,但这对于缓存的值没有意义.在缓存本身的实现中做一些事情是有意义的,例如用新结果替换过时的条目.
这本字典的值,因为它是只读的,可以是List<T>与没有不良影响,即使它会从多个线程访问.您可以使用它List<T>.AsReadOnly来增强您的信心并添加一些编译时安全检查.
但重要的是,List<T>如果它是可变的,那么它只是不是线程安全的.因为根据定义,使用缓存实现的方法如果多次调用必须返回相同的值(直到缓存本身使值无效),客户端无法修改返回的值,因此List<T>必须冻结,实际上是不可变的.
如果客户端迫切需要修改缓存的数据库结果并且值为a List<T>,那么唯一安全的方法是:
总之,对顶级缓存使用线程安全字典,对缓存值使用普通列表,注意在将其插入缓存后永远不要修改最后一个内容.
| 归档时间: |
|
| 查看次数: |
8425 次 |
| 最近记录: |