ConcurrentDictionary.AddOrUpdate,将更新过时的值?

问题描述 投票:0回答:1

我对

AddOrUpdate
方法感到困惑。文档特别说
updateValueFactory
不同步。

MSDN 中给出了这个例子:

 Parallel.For(0, 10000, i =>
 {
     // Initial call will set cd[1] = 1.   
     // Ensuing calls will set cd[1] = cd[1] + 1
     cd.AddOrUpdate(1, 1, (key, oldValue) => oldValue + 1);
 });

如果有多个线程尝试增加

oldvalue
,那么其中一些线程是否可能会更新过时的值?

谢谢。

c# .net concurrency thread-safety concurrentdictionary
1个回答
0
投票

如果有多个线程尝试增加旧值,那么其中一些线程是否可能会更新过时的值?

不。仅当没有其他线程同时更新该值时,

updateValueFactory
返回的值才会存储在字典中。否则,如果值已更改,则会再次调用
updateValueFactory
,并以新的当前值作为参数。
updateValueFactory
会根据需要多次调用,直到当前线程赢得更新字典的乐观竞赛。

下面显示了如何将

AddOrUpdate
实现为扩展方法,以防它本身不可用:

public static TValue AddOrUpdate<TKey, TValue>(
    this ConcurrentDictionary<TKey, TValue> source,
    TKey key,
    TValue addValue,
    Func<TKey, TValue, TValue> updateValueFactory)
{
    ArgumentNullException.ThrowIfNull(source);
    ArgumentNullException.ThrowIfNull(updateValueFactory);
    while (true)
    {
        if (source.TryGetValue(key, out TValue existingValue))
        {
            TValue newValue = updateValueFactory(key, existingValue);
            if (source.TryUpdate(key, newValue, existingValue)) return newValue;
        }
        else
        {
            if (source.TryAdd(key, addValue)) return addValue;
        }
        // We lost the race. Let's try again.
    }
}
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.