Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ConcurrentDictionary中的AddOrUpdate线程安全吗?_C#_Multithreading - Fatal编程技术网

C# ConcurrentDictionary中的AddOrUpdate线程安全吗?

C# ConcurrentDictionary中的AddOrUpdate线程安全吗?,c#,multithreading,C#,Multithreading,我尝试在ConcurrentDictionary中使用AddOrUpdate方法 从本页的“备注”部分。上面说 但是,这些方法的委托在锁外部被调用,以避免在锁下执行未知代码时可能出现的问题。因此,这些委托执行的代码不受操作原子性的约束 所以我不确定它是否是线程安全的。我有一个例子,如果找不到键,则值为1,否则将值增加1 我写了下面的函数 private static void AddOrUpdate(ConcurrentDictionary<string, int> map)

我尝试在ConcurrentDictionary中使用AddOrUpdate方法

从本页的“备注”部分。上面说

但是,这些方法的委托在锁外部被调用,以避免在锁下执行未知代码时可能出现的问题。因此,这些委托执行的代码不受操作原子性的约束

所以我不确定它是否是线程安全的。我有一个例子,如果找不到键,则值为1,否则将值增加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();
        }
    }
private static void addor更新(ConcurrentDictionary映射)
{
随机r=新随机();
睡眠(r.Next(10));
map.AddOrUpdate(键,1,(键,值)=>value+1);
}
公共静态void TestThreadSafe(ConcurrentDictionary映射)
{
螺纹[]螺纹=新螺纹[尺寸];
对于(int i=0;iAddOrUpdate(map));
}
foreach(线程中的var线程)
{
thread.Start();
}
}
创建了大约300000个线程并并行运行。结果总是30万


上述方法是线程安全的吗?AddOrUpdate何时不是线程安全的?

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

例如:

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; });
    }
private static void addor更新(ConcurrentDictionary映射)
{
随机r=新随机();
睡眠(r.Next(10));
map.AddOrUpdate(键,1,(键,值)=>{Console.WriteLine(键+”:“+value);返回值+1;});
}
可以多次打印同一个键+值


有时ConcurrentDictionary可能会在多个线程上执行这些方法,然后获取结果值并输入锁以尝试应用它。其中一个线程将成功,另一个线程将进入锁,查看该值在读取后是否已更改,然后重试该委托。

线程安全与否,尝试创建300000个线程(您将遇到一个)对于您的场景可能不是一个好主意
Parallel.ForEach
更友好一个例子是
dict.AddOrUpdate(…,…,(k,v)=>v.Add(item)),其中字典包含一个普通的泛型列表,可能会将该项添加到引用类型中两次。