Is AddOrUpdate thread safe in ConcurrentDictionary?

和自甴很熟 提交于 2020-12-29 06:08:40

问题


I tried to use AddOrUpdate method in ConcurrentDictionary.

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."

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.

I wrote below function

    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();
        }
    }

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

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


回答1:


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.

For example:

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.

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.



来源:https://stackoverflow.com/questions/39156752/is-addorupdate-thread-safe-in-concurrentdictionary

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!