简体   繁体   English

使用 foo[bar] = baz 添加到 ConcurrentDictionary 是否线程安全?

[英]Is it threadsafe to add to a ConcurrentDictionary using foo[bar] = baz?

I'm not a fan of the methods attached to the ConcurrentDictionary .我不喜欢附加到ConcurrentDictionary的方法。 AddOrUpdate requires a func and GetOrAdd adds when you are just looking for the key to get the value. AddOrUpdate需要一个函数,当您只是在寻找获取值的键时,会添加GetOrAdd So I want to use it like a normal dictionary (I'm using ContainsKey to be safe)所以我想像普通字典一样使用它(我使用ContainsKey是安全的)

The docs say "To store a key/value pair in the dictionary unconditionally, and overwrite the value of a key that already exists", use The indexer's setter: dictionary[key] = newValue . 文档说“要无条件地将键/值对存储在字典中,并覆盖已经存在的键的值”,请使用索引器的设置器: dictionary[key] = newValue

But is this operation still threadsafe?但是这个操作仍然是线程安全的吗? The comments at the bottom say "All public and protected members of ConcurrentDictionary are thread-safe and may be used concurrently from multiple threads."底部的评论说“ConcurrentDictionary 的所有公共和受保护成员都是线程安全的,可以从多个线程同时使用。” But I'm not 100% sure that they consider the above setter to be included here.但我不是 100% 确定他们认为上面的 setter 包含在此处。

You can check the indexer implementation of ConcurrentDictionary at reference source -- https://referencesource.microsoft.com/#mscorlib/system/Collections/Concurrent/ConcurrentDictionary.cs您可以在参考源检查ConcurrentDictionaryindexer实现 -- https://referencesource.microsoft.com/#mscorlib/system/Collections/Concurrent/ConcurrentDictionary.cs

    public TValue this[TKey key]
    {
        get
        {
            TValue value;
            if (!TryGetValue(key, out value))
            {
                throw new KeyNotFoundException();
            }
            return value;
        }
        set
        {
            if (key == null) throw new ArgumentNullException("key");
            TValue dummy;
            TryAddInternal(key, value, true, true, out dummy);
        }
    }

If you notice the setter calls TryAddInternal which is thread safe implementation如果您注意到 setter 调用TryAddInternal这是线程安全的实现

在此处输入图像描述

It is thread-safe in the sense that the internal state of the ConcurrentDictionary will not be corrupted.ConcurrentDictionary的内部 state 不会被破坏的意义上,它是线程安全的。 This is the main guarantee offered by this class.这是此 class 提供的主要保证。 So if you call foo[bar] = fiz from one thread and foo[bar] = biz from another thread concurrently, then either fiz or biz will be finally stored as a value of the key bar , provided that this key already existed in the collection (otherwise an exception will be thrown by both threads).因此,如果您同时从一个线程调用foo[bar] = fiz并同时从另一个线程调用 foo[bar foo[bar] = biz ,那么fizbiz最终将存储为键bar的值,前提是该键已经存在于集合(否则两个线程都会抛出异常)。

It's as if foo[bar] was a variable with a size of a native integer or smaller, for example short count;就好像foo[bar]是一个大小为原生 integer 或更小的变量,例如short count; . . It is safe to update this variable from multiple threads, in the sense that its internal bits will not be partially updated, and will always hold the last value assigned.从多个线程更新此变量是安全的,因为它的内部位不会被部分更新,并且将始终保存最后分配的值。 If this guarantee is not enough for your program, if for example you want the count to hold something meaningful, like how many times has been updated, then you'll have to synchronize the access to this variable.如果这个保证对你的程序来说还不够,例如你想让count保持有意义的东西,比如更新了多少次,那么你必须同步对这个变量的访问。

In the case of ConcurrentDictionary , if you want the foo[bar] to hold the value biz only if it was previously fiz , then this is not thread-safe: if (foo[bar] == fiz) foo[bar] = biz .ConcurrentDictionary的情况下,如果您希望foo[bar]仅在之前为fiz时才保留值biz ,那么这不是线程安全的: if (foo[bar] == fiz) foo[bar] = biz . You'll have to use the TryUpdate method: foo.TryUpdate(bar, biz, fiz) .您必须使用TryUpdate方法: foo.TryUpdate(bar, biz, fiz) Another case: if you want the foo[bar] to hold the value biz only if it was not previously fiz , then you are out of luck.另一种情况:如果您希望foo[bar]仅在以前不是fiz的情况下才保留值biz ,那么您就不走运了。 The ConcurrentDictionary does not include a method that offers this guarantee. ConcurrentDictionary不包括提供此保证的方法。 So you'll be forced to go back in using a Dictionary + manual synchronization.因此,您将被迫使用Dictionary +手动同步返回 go 。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Function 被测 “foo” 调用外部 function “bar(baz)” 多次 =&gt; 如何针对每个调用专门修改 “baz” 的返回值? - Function under test “foo” calls external function “bar(baz)” multiple times => How can return value of “baz” be modified specifically for each call? foo.Include(x =&gt; x.bar.Select(y =&gt; y.baz)是否在C#中包含foo.bar? - Does foo.Include(x => x.bar.Select(y => y.baz) include foo.bar in C#? 对ConcurrentDictionary Values的linq查询是否是线程安全的? - Is a linq query to ConcurrentDictionary Values threadsafe? ConcurrentDictionary Keys 或 Values 属性是线程安全的 - Is ConcurrentDictionary Keys or Values property threadsafe 为什么会收到虚假的TypeLoadException“方法 <foo> 在类型上 <bar> 从组装 <baz> 没有实现”? - Why do I get a spurious TypeLoadException “Method <foo> in type <bar> from assembly <baz> does not have an implementation”? ConcurrentDictionary是否可以在GetOrAdd之后编辑值? - ConcurrentDictionary is it threadsafe to edit the value after a GetOrAdd? 当与ConcurrentDictionary <Tkey,TValue>一起使用时,C#LINQ OrderBy线程是否安全? - Is C# LINQ OrderBy threadsafe when used with ConcurrentDictionary<Tkey, TValue>? ConcurrentDictionary 添加数据 - ConcurrentDictionary Add Data 为什么在使用ConcurrentDictionary时不能将null添加为值? - Why can I not add null as a value when using ConcurrentDictionary? 在Web服务中使用ConcurrentDictionary - Using a ConcurrentDictionary in webservice
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM