gpt4 book ai didi

c# - 如何在 .NET ConcurrentDictionary 中实现 remove_if 功能

转载 作者:可可西里 更新时间:2023-11-01 08:42:53 26 4
gpt4 key购买 nike

我有一个场景,我必须为 ConcurrentDictionary 中的给定键保留引用计数对象,如果引用计数达到 0,我想删除该键。这必须是线程安全的,因此我计划使用 ConcurrentDictionary

示例程序如下。在并发字典中,我有 key 和 value ,值是 KeyValuePair ,它保存我的自定义对象和引用计数。

ConcurrentDictionary<string, KeyValuePair<object, int>> ccd = 
new ConcurrentDictionary<string, KeyValuePair<object, int>>();

// following code adds the key, if not exists with reference
// count for my custom object to 1
// if the key already exists it increments the reference count

var addOrUpdateValue = ccd.AddOrUpdate("mykey",
new KeyValuePair<object, int>(new object(), 1),
(k, pair) => new KeyValuePair<object, int>(pair.Key, pair.Value + 1));

现在我想要一种在引用计数达到 0 时删除键的方法。我在想,ConcurrentDictionary 上的 remove 方法接受键和谓词,如果谓词返回 'true,则删除键'.示例。

ConcurrentDictionary.remove(TKey, Predicate<TValue> ). 

ConcurrentDictionary 上没有这样的方法,问题是如何以线程安全的方式做同样的事情?。

最佳答案

.NET 不公开 RemoveIf直接,但它确实公开了使其工作所需的构建 block ,而无需您自己进行锁定。

ConcurrentDictionary工具 ICollection<T> , 它有一个 Remove需要并测试完整的 KeyValuePair而不仅仅是一把 key 。尽管被隐藏了,这个 Remove仍然是线程安全的,我们将使用它来实现它。要让它起作用,需要注意的是 Remove使用 EqualityComparer<T>.Default要检验值(value),所以它必须是平等可比的。您当前的不是,因此我们将重新实现它:

struct ObjectCount : IEquatable<ObjectCount>
{
public object Object { get; }
public int Count { get; }

public ObjectCount(object o, int c)
{
Object = o;
Count = c;
}

public bool Equals(ObjectCount o) =>
object.Equals(Object, o.Object) && Count == o.Count;

public override bool Equals(object o) =>
(o as ObjectCount?)?.Equals(this) == true;

// this hash combining will work but you can do better.
// it is not actually used by any of this code.
public override int GetHashCode() =>
(Object?.GetHashCode() ?? 0) ^ Count.GetHashCode();
}

最后,我们将定义一个方法来增加/减少字典中的计数:

void UpdateCounts(ConcurrentDictionary<string, ObjectCount> dict, string key, int toAdd)
{
var addOrUpdateValue = dict.AddOrUpdate(key,
new ObjectCount(new object(), 1),
(k, pair) => new ObjectCount(pair.Key, pair.Value + toAdd));

if(addOrUpdateValue.Count == 0)
{
((ICollection<KeyValuePair<string, ObjectCount>>)dict).Remove(
new KeyValuePair<string, ObjectCount>(key, addOrUpdateValue));
}
}

AddOrUpdate 的调用之间可能会更改该键的值和 Remove ,但这对我们来说并不重要:因为 Remove测试完整 KeyValuePair , 它只会在更新后该值未更改的情况下将其删除。

这是一种常见的无锁模式,即设置一个更改,然后使用最终的线程安全操作来安全地“提交”更改,前提是我们的数据结构在此期间没有更新。

关于c# - 如何在 .NET ConcurrentDictionary 中实现 remove_if 功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39679779/

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