如何执行在C#中的线程安全功能的memoization? [英] How to perform thread-safe function memoization in c#?
问题描述
下面的堆栈溢出我已经发现的code表示memoizes单参数功能:
Here on stack overflow I've found the code that memoizes single-argument functions:
static Func<A, R> Memoize<A, R>(this Func<A, R> f)
{
var d = new Dictionary<A, R>();
return a=>
{
R r;
if (!d.TryGetValue(a, out r))
{
r = f(a);
d.Add(a, r);
}
return r;
};
}
虽然这code做了这个工作对我来说,这有时会失败时memoized功能,同时从多个线程调用:在添加
方法被调用两次相同的参数,并抛出一个异常。
While this code does its job for me, it fails sometimes when the memoized function is called from the multiple threads simultaneously: the Add
method gets called twice with the same argument and throws an exception.
我怎样才能让记忆化线程安全的?
How can I make the memoization thread-safe?
推荐答案
您可以使用<一个href="http://msdn.microsoft.com/en-us/library/ee378676%28v=vs.110%29.aspx"><$c$c>ConcurrentDictionary.GetOrAdd$c$c>它做了你需要的一切:
You can use ConcurrentDictionary.GetOrAdd
which does everything you need:
static Func<A, R> ThreadsafeMemoize<A, R>(this Func<A, R> f)
{
var cache = new ConcurrentDictionary<A, R>();
return argument => cache.GetOrAdd(argument, f);
}
功能 F
应该是线程安全的本身,因为它可以从多个线程同时调用。
The function f
should be threadsafe itself, because it can be called from multiple threads simultaneously.
这code也不能保证功能可按 F
被称为每个唯一参数值只有一次。它可以被调用多次,事实上,在繁忙的环境。如果你需要这样的合同,你应该看一看在这个相关问题的答案,但被警告,他们是不紧凑,并且需要使用锁。
This code also doesn't guarantee that funciton f
is called only once per unique argument value. It can be called many times, in fact, in the busy environment. If you need this kind of contract, you should take a look at the answers in this related question, but be warned that they're not as compact and require using locks.
这篇关于如何执行在C#中的线程安全功能的memoization?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!