【发布时间】:2020-06-11 16:10:12
【问题描述】:
在他的.NET 中的并发一书中,Riccardo Terrell 提供了两个版本的 Memoize 函数(如下),并声称第二个函数比第一个函数执行得更好,因为它避免了重复的缓存项初始化,同时还线程安全。
我的问题是 - 第二个版本是否仍然会导致重复的缓存项初始化?
对于添加到字典中的每个键/值对,一个 new 惰性实例被初始化并返回,这意味着 X 线程可能会导致 X 惰性类型被初始化,最终导致 X 调用 func(a),这正是函数的第一个版本中发生的情况?从我所见,看起来第二版的行为与第一版完全相同。
版本 1
public Func<T, R> MemoizeThreadSafe<T, R>(Func<T, R> func) where T : IComparable
{
ConcurrentDictionary<T, R> cache = new ConcurrentDictionary<T, R>(); ①
return arg => cache.GetOrAdd(arg, a => func(a));
}
第 2 版
static Func<T, R> MemoizeLazyThreadSafe<T, R>(Func<T, R> func) where T : IComparable
{
ConcurrentDictionary<T, Lazy<R>> cache = new ConcurrentDictionary<T, Lazy<R>>(); ①
return arg => cache.GetOrAdd(arg, a => new Lazy<R>(() => func(a))).Value;
}
【问题讨论】: