gpt4 book ai didi

c# - 在线程之间共享字典中的数据

转载 作者:行者123 更新时间:2023-11-30 20:23:14 27 4
gpt4 key购买 nike

假设代码:

class Memory {
Dictionary<int, int> m_values;
Object lockObject = new Object();

public int GetData(int key) {
int result;
lock (lockObject) {
if (!m_values.TryGetValue(key, out result)) {
result = VeryExpensiveComputationMethod(key);
m_values[key] = result;
}
}
return result
}
}

这是安全的,但问题是它不是很有效。知道如何使用 .NET 2.0 兼容代码更好地做到这一点吗? (在最好的情况下,只有等待相同键的相同结果的线程应该等待)

最佳答案

如果您使用 ConcurrentDictionary而不是 Dictionary您将获得两项关键改进:

  1. 您无需为显式锁定而烦恼
  2. 你有一个(保证是原子性的)GetOrAdd让您从字典中获取值或在不存在值时添加值的方法。

结合使用 Lazy<T> ,它允许您创建一个对象,该对象将其值定义为昂贵计算的结果,它确保只运行一次,只在需要时运行,然后缓存并在重复询问该值时一次又一次地返回。

我们现在可以创建一个 ConcurrentDictionary<int, Lazy<int>> ,在这两种类型之间,它基本上为我们做了所有的工作:

请注意,一旦我们得到 LazyGetOrAdd 返回这意味着:

  1. 它是一个甚至还没有开始计算值的新懒惰,在这种情况下它将计算值并返回它。
  2. 它是一个现有的懒惰,具有可以立即返回的已经计算的值。
  3. 这是一个现有的懒惰,其值尚未完成计算;它将等到操作完成,然后该值将返回给所有等待其计算的调用。

在任何情况下都不会 VeryExpensiveComputationMethod为同一个键多次调用。

private ConcurrentDictionary<int, Lazy<int>> values =
new ConcurrentDictionary<int, Lazy<int>>();

public int GetData(int key)
{
//Note that this doesn't actually run VeryExpensiveComputationMethod
//until .Value is called on it
var lazy = new Lazy<int>(() => VeryExpensiveComputationMethod(key));
return values.GetOrAdd(key, lazy).Value;
}

就 .NET 2.0 解决方案而言,您没有任何一种类型。使用 Dictionary并且锁定当然是可行的,只是不太干净:

private Dictionary<int, Lazy<int>> values;
private object sync = new object();
public int GetData(int key)
{
Lazy<int> lazy;
lock (sync)
{
if (!values.TryGetValue(key, out lazy))
{
lazy = new Lazy<int>(delegate
{
return VeryExpensiveComputationMethod(key);
});
values.Add(key, lazy);
}
}
return lazy.Value;
}

至于Lazy ,您只需要创建自己的版本:

public delegate T Func<T>();
public class Lazy<T>
{
private object key = new object();
private Func<T> generator;
private T value;
public Lazy(Func<T> generator)
{
this.generator = generator;
}

private volatile bool hasComputedValue;
public bool HasComputedValue { get { return hasComputedValue; } }

public T Value
{
get
{
lock (key)
{
if (HasComputedValue)
return value;
else
{
value = generator();
hasComputedValue = true;
generator = null;
return value;
}
}
}
}
}

关于c# - 在线程之间共享字典中的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29416832/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com