gpt4 book ai didi

.net - atomic addorupdate(尝试使用并发字典编写命名储物柜)

转载 作者:行者123 更新时间:2023-12-04 12:54:53 24 4
gpt4 key购买 nike

ConcurrentDictionary Pitfall - Are delegates factories from GetOrAdd and AddOrUpdate synchronized?注意 AddOrUpdate 不是原子的(并且不能保证委托(delegate)不会运行超过一次)。

我正在尝试使用并发字典来实现名称锁定实现,例如 here ,但是字典不应该永远增长,就像这样:

public class ConcurrentDictionaryNamedLocker : INamedLocker
{
// the IntObject values serve as the locks and the counter for how many RunWithLock jobs
// are about to enter or have entered the critical section.
private readonly ConcurrentDictionary<string, IntObject> _lockDict = new ConcurrentDictionary<string, IntObject>();
private static readonly IntObject One = new IntObject(1);
private readonly Func<string, IntObject, IntObject> _decrementFunc = (s, o) => o - 1;
private readonly Func<string, IntObject, IntObject> _incrementFunc = (s, o) => o + 1;
private readonly Func<string, IntObject> _oneFunc = s => new IntObject(1);
private readonly Func<string, IntObject> _zeroFunc = s => new IntObject(0);

public TResult RunWithLock<TResult>(string name, Func<TResult> body)
{
name = name.ToLower();
TResult toReturn;
lock (_lockDict.AddOrUpdate(name, _oneFunc, _incrementFunc))
{
toReturn = body();
if (!_lockDict.TryRemove(name, One))
_lockDict.AddOrUpdate(name, _zeroFunc, _decrementFunc);
}
return toReturn;
}

public void RunWithLock(string name, Action body)
{
name = name.ToLower();
lock (_lockDict.AddOrUpdate(name, _oneFunc, _incrementFunc))
{
body();
if (!_lockDict.TryRemove(name, One))
_lockDict.AddOrUpdate(name, _zeroFunc, _decrementFunc);
}
}
}

但问题是 AddOrUpdate 不是原子的,所以我看到当存在争用时条目通常不会被删除。我相当肯定,如果 AddOrUpdate 是原子的,那么上面的代码将完成它的工作并且条目将被适本地删除。

注意使用 key+val 扩展方法的条件删除 TryRemove(key,val) 提到 here .此外,IntObject 是一个简单的 int 可变对象包装器。

我有哪些选择?是否有任何并发​​字典实现具有 1. 原子条件(键和值)删除和 2. AddOrUpdate 是原子的并确保委托(delegate)不会多次运行?

还有其他想法吗?我希望命名的储物柜速度快,但在给定无限锁定命名空间但对给定名称没有太多争用的情况下没有内存压力问题。据我所知,按名称进行的字符串实习锁定会永远增长,并且永远不会被清理并具有其他副作用。并且互斥锁是半慢的并且有各种烦恼(260个字符限制)。

最佳答案

查看 IntValue 的确切代码会有所帮助因为那是在 AddOrUpdate 中运行的代码代表。

我认为问题在于代码需要 IntValue两个实例:

  • 可变以锁定单个 IntValue与每个字符串关联的实例(尽管稍后引用计数增加)
  • 不可变以便比较 IntValue s 到静态 One作为删除标准

  • 如果我将代码更改为 IntValue支持一个不可变的零,这似乎有效:
    private readonly Func<string, IntObject> _zeroFunc = s => IntObject.Zero;

    ...
    public void RunWithLock(string name, Action body)
    {
    name = name.ToLower();
    lock (_lockDict.AddOrUpdate(name, _oneFunc, _incrementFunc))
    {
    body();
    _lockDict.AddOrUpdate(name, _zeroFunc, _decrementFunc);
    _lockDict.TryRemove(name, IntObject.Zero);
    }
    }

    但我选择实现 IntValue像这样的方法和非运算符(operator):
        internal IntObject Dec(int p)
    {
    var newVal = Interlocked.Decrement(ref value);
    if (newVal == 0) return Zero;
    return this;
    }

    关于.net - atomic addorupdate(尝试使用并发字典编写命名储物柜),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17287235/

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