在ConcurrentDictionary中AddOrUpdate线程安全吗? [英] Is AddOrUpdate thread safe in ConcurrentDictionary?

查看:108
本文介绍了在ConcurrentDictionary中AddOrUpdate线程安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试在ConcurrentDictionary中使用AddOrUpdate方法.

I tried to use AddOrUpdate method in ConcurrentDictionary.

从此页上的备注"部分https://msdn.microsoft.com/zh-CN/library/dd287191(v=vs.110).aspx .它说

From the "Remarks" section on this page https://msdn.microsoft.com/en-us/library/dd287191(v=vs.110).aspx. it says

但是,这些方法的委托在锁之外调用,以避免由于执行锁下的未知代码而引起的问题.因此,这些委托执行的代码不受制于操作的原子性."

"However, delegates for these methods are called outside the locks to avoid the problems that can arise from executing unknown code under a lock. Therefore, the code executed by these delegates is not subject to the atomicity of the operation."

所以我不确定它是否是线程安全的.我有一种情况,如果找不到键,则值为1,否则将值增加1.

So I am not sure whether it is thread safe. I have one case, if the key is not found, the value is 1, otherwise increase the value by 1.

我写了下面的函数

    private static void AddOrUpdate(ConcurrentDictionary<string, int> map)
    {
        Random r = new Random();
        Thread.Sleep(r.Next(10));
        map.AddOrUpdate(Key, 1, (key, value) => value + 1);
    }

    public static void TestThreadSafe(ConcurrentDictionary<string, int> map)
    {
        Thread[] threads = new Thread[Size];
        for (int i = 0; i < Size; ++i)
        {
            threads[i] = new Thread(() => AddOrUpdate(map));
        }

        foreach (var thread in threads)
        {
            thread.Start();
        }
    }

创建了大约300,000个线程并并行运行它们.结果始终为300,000.

created about 300,000 threads and run them in parallel. The results are always 300,000.

以上方法线程安全吗?什么时候AddOrUpdate不是线程安全的?

Is above method thread safe? When is AddOrUpdate not thread safe?

推荐答案

在使用中它是线程安全的.当传递给 AddOrUpdate 的委托具有副作用时,它将变得不是线程安全的,因为对于相同的键和现有值,这些副作用可能会执行两次.

It is thread safe in your usage. It becomes not thread safe when the delegate passed to AddOrUpdate has side effects, because those side effects may be executed twice for the same key and existing value.

例如:

private static void AddOrUpdate(ConcurrentDictionary<string, int> map)
    {
        Random r = new Random();
        Thread.Sleep(r.Next(10));
        map.AddOrUpdate(Key, 1, (key, value) => { Console.WriteLine(key + ": " + value); return value + 1; });
    }

可能多次打印相同的键+值.

May print the same key + value more than once.

发生的事情是,有时ConcurrentDictionary可能会在多个线程上执行这些方法,然后获取结果值并输入锁以尝试并应用它.一个线程将成功,另一个线程将进入锁,看到值自读取以来已更改,然后再次尝试委托.

What happens is that sometimes the ConcurrentDictionary may execute those methods on multiple threads, then take the resulting value and enter the lock to try and apply it. One of the threads will succeed, and the other will then enter the lock, see that the value has changed since it read it, and try the delegate again.

这篇关于在ConcurrentDictionary中AddOrUpdate线程安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆