C# 在插入ConcurrentDictionary时使用惰性计算是否会阻止多次计算请求的值?

C# 在插入ConcurrentDictionary时使用惰性计算是否会阻止多次计算请求的值?,c#,.net,C#,.net,Riccardo Terrell在其著作《.NET中的并发》(Concurrency In.NET)中提供了两个版本的Memoize函数(见下文),并声称第二个函数的性能优于第一个函数,因为它避免了重复的缓存项初始化,同时也是线程安全的 我的问题是-第二个版本是否仍然会导致重复的缓存项初始化 对于添加到字典中的每个键/值对,都会初始化并返回一个新的惰性实例,这意味着X个线程可能会导致X个惰性类型被初始化,最终导致X个func(a)调用,这正是函数的第一个版本中发生的情况?从我看到的情况来看,第二

Riccardo Terrell在其著作《.NET中的并发》(Concurrency In.NET)中提供了两个版本的Memoize函数(见下文),并声称第二个函数的性能优于第一个函数,因为它避免了重复的缓存项初始化,同时也是线程安全的

我的问题是-第二个版本是否仍然会导致重复的缓存项初始化

对于添加到字典中的每个键/值对,都会初始化并返回一个新的惰性实例,这意味着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));
}
public Func MemoizeThreadSafe(Func Func)其中T:i可比较
{
ConcurrentDictionary缓存=新建ConcurrentDictionary();①  
返回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;
}
static Func MemoizeLazyThreadSafe(Func Func)其中T:i可比较
{
ConcurrentDictionary缓存=新建ConcurrentDictionary();①  
返回arg=>cache.GetOrAdd(arg,a=>newlazy(()=>func(a))).Value;
}

GetOrAdd
将始终返回相同的值。两个线程可能会竞相为同一个参数值创建一个
惰性
,但它们最终都只会引用其中一个。它们都会依次调用它的
Value
,它会自己初始化一次。只有对
Value
的调用才强制执行此初始化,并且只有在该调用之后才会调用
func(a)

另一个
Lazy
将被放弃,并最终成为GCed1,而无需初始化其值



1假设GC将来会运行,那么您就不会使用空GC等运行。

GetOrAdd
将始终返回相同的值。两个线程可能会竞相为同一个参数值创建一个
惰性
,但它们最终都只会引用其中一个。它们都会依次调用它的
Value
,它会自己初始化一次。只有对
Value
的调用才强制执行此初始化,并且只有在该调用之后才会调用
func(a)

另一个
Lazy
将被放弃,并最终成为GCed1,而无需初始化其值



1假设GC将来会运行,那么您不会使用空GC运行。

太好了,谢谢。我没有想到会创建两个
Lazy
,但只会访问其中一个的值,因此不会初始化另一个中包含的值。太好了,谢谢。我没有想到会同时创建
Lazy
,但只会访问其中一个的值,因此不会初始化另一个中包含的值。