一种常见的缓存习惯用法是检查缓存中是否存在项目,检索是否存在,否则创建。
这是否会创建一个条件,如果在注释位置发生从Thread 1
到Thread 2
的上下文切换,则当上下文切换回{{{}时,可能会立即覆盖添加到缓存的值。 1}}发生?缺点是Thread 1
现在已被调用两次以计算相同的缓存项。这只是这个简单缓存实现的可接受的“次要”后果。是否通常不使用关键部分,因为这会增加所有calculateFooBar()
方法的开销?
编辑:_cache是对共享数据缓存的引用(例如ASP.NET数据缓存)。
GetOrCreate
答案 0 :(得分:1)
一切都取决于这个_cache
变量是什么:它的类型和范围。如果它是静态变量而不是线程安全的,例如Dictionary<TKey, TValue>
,则需要使用lock
来同步对它的访问。在.NET 4.0中,您使用ConcurrentDictionary<TKey, TValue>
类型,以线程安全的方式实现类似的功能。你的代码很好,但没有lock
,不能保证在很短的时间内对同一个密钥不会发生两次计算。
您可以查看following blog post以获得此模式的一个很好的实现。此外,如果您使用的是.NET 4.0,则可以使用新的System.Runtime.Caching程序集。
答案 1 :(得分:1)
如果您的程序正常工作,即使您有该对象的两个实例,并且只有资源分配时间&amp;内存是你关注的我不会打扰添加锁。从长远来看,线程同步可能更昂贵。
ConcurrentDictionary&LT;&GT;对于这样的“nolock”容器来说,这将是一个不错的选择,正如其他人已经提到的那样。
答案 2 :(得分:1)
我们在几个场景中使用了一些自定义缓存......新的Concurrent
* - .NET 4中的集合非常适合这种命令......
如果foobars
为ConcurrentDictionary<string, FooBar>
,您可以执行以下操作:
return foobars.GetOrAdd (key, (k) => calculateFooBar() );
此代码将替换您的整个样本方法GetOrCreate
。