Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.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?_C#_.net_Thread Safety_Concurrentdictionary - Fatal编程技术网

C# 添加或更新时是否锁定ConcurrentDictionary?

C# 添加或更新时是否锁定ConcurrentDictionary?,c#,.net,thread-safety,concurrentdictionary,C#,.net,Thread Safety,Concurrentdictionary,我使用ConcurrentDictionAnry跨多个线程访问一些数据 我读到(向下滚动)锁中没有执行方法AddOrUpdate,因此可能会危及线程安全 我的代码如下: //keys and bar are not the concern here ConcurrentDictioanry<string, HashSet<string>> foo = new ...; foreach(var key in keys) { foo.AddOrUpdate(key,

我使用
ConcurrentDictionAnry
跨多个线程访问一些数据

我读到(向下滚动)锁中没有执行方法
AddOrUpdate
,因此可能会危及线程安全

我的代码如下:

//keys and bar are not the concern here
ConcurrentDictioanry<string, HashSet<string>> foo = new ...;
foreach(var key in keys) {
    foo.AddOrUpdate(key, new HashSet<string> { bar }, (key, val) => {
        val.Add(bar);
        return val;
    });
}
//这里不关心键和条
ConcurrentDictionAnry foo=新。。。;
foreach(var键入键){
AddOrUpdate(key,new HashSet{bar},(key,val)=>{
val.Add(bar);
返回val;
});
}

我是否应该将
AddOrUpdate
调用包含在
lock
语句中,以确保一切都是线程安全的?

AddOrUpdate
期间单独锁定不会有帮助-您仍然必须在每次读取集合时锁定

如果要将此集合视为线程安全的,则确实需要这些值也是线程安全的。理想情况下,您需要一个
ConcurrentSet
。现在,框架中不存在这一点(除非我遗漏了什么),但是您可以创建自己的
ConcurrentSet
,它使用
concurrentdirectionary
(或者您喜欢的任何
TValue
)作为其底层数据结构。基本上,您会忽略字典中的值,而只将键的存在视为重要部分

您不需要实现ISet中的所有内容,只需要实际需要的位


然后,您可以在应用程序代码中创建一个
ConcurrentDictionary
,这样您就不需要锁定了。

这篇文章指出,add委托没有在字典的锁中执行,您得到的元素可能不是add委托在该线程中创建的元素。这不是线程安全问题;字典的状态将是一致的,所有调用方都将获得相同的实例,即使为每个调用方创建了不同的实例(并且除一个实例外,所有调用方都将被删除)。

您需要修复此代码,它会产生大量垃圾。即使不需要任何哈希集,也可以创建新的哈希集。使用另一个重载,即接受valueFactory委托的重载。因此,哈希集仅在密钥尚未出现在字典中时创建


如果多个线程同时尝试添加键的相同值,但该值不存在,则可能会多次调用valueFactory。几率很低,但不是零。将只使用其中一个哈希集。这不是问题,创建HashSet没有可能导致线程问题的副作用,额外的副本只是被垃圾收集。

似乎更好的答案是在传递委托的方法上使用Lazy


另外还有一篇关于延迟加载add委托的好文章

如果通过API访问(读写)我的
ConcurrentDictionary
实例会怎么样?所以客户端代码实际上不会注意到有一个
ConcurrentDictionary
,那么我可以安全地在API的公共方法中进行锁定,对吗?我只是想了解这里的情况…@保罗:是的,你可以确保每次访问任何东西时都能锁定。。。但是你认为ConcurrentDictionary真正为你买了什么?请看我的问题,正是关于这个问题:谢谢,通过使用另一个重载修复了这个问题。