- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我有一个场景,我必须为 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/
我是一名优秀的程序员,十分优秀!