我有以下代码来缓存我在多线程应用程序中使用的并发字典中某些类的实例。
简单地说,当我用 id 参数实例化类时,它首先检查字典中是否存在具有给定 id 的 privateclass 实例,如果不存在则创建 privateclass 的实例(这需要很长时间,有时需要几秒钟),并将其添加到字典中以备将来使用。
public class SomeClass
{
private static readonly ConcurrentDictionary<int, PrivateClass> SomeClasses =
new ConcurrentDictionary<int, PrivateClass>();
private readonly PrivateClass _privateClass;
public SomeClass(int cachedInstanceId)
{
if (!SomeClasses.TryGetValue(cachedInstanceId, out _privateClass))
{
_privateClass = new PrivateClass(); // This takes long time
SomeClasses.TryAdd(cachedInstanceId, _privateClass);
}
}
public int SomeCalculationResult()
{
return _privateClass.CalculateSomething();
}
private class PrivateClass
{
internal PrivateClass()
{
// this takes long time
}
internal int CalculateSomething()
{
// Calculates and returns something
}
}
}
我的问题是,我是否需要在外部类构造函数的生成和赋值部分周围添加一个锁,以使这个代码线程安全,还是它本来就很好?
更新:
在 SLaks 的建议下,尝试使用ConcurrentDictionary 的GetOrAdd()方法和Lazy的组合,但不幸的是,构造函数PrivateClass
仍然调用了不止一次。测试代码见https://gist.github.com/3500955。
更新 2:您可以在此处查看最终解决方案: https ://gist.github.com/3501446