Is ConcurrentDictionary Keys or Values property threadsafe

邮差的信 提交于 2020-06-10 02:07:25

问题


Have a question regarding thread safety with ConcurrentDictionary. From the API, I see that the enumerator is thread-safe, but I don't see the same for keys and values properties. My question is:

Is it safe to loop over the Keys or Values collection when there are other threads modifying it concurrently?


回答1:


While I do like the documentation, I tend to verify things with a small program when in doubt or I feel that I might be assuming too much.

The following code verifies that indeed you can enumerate the values collection safely while adding or removing keys from a separate thread to that on which the enumeration is taking place. This will not cause the usual collection was modified exceptions. In more detail, here are a couple of test cases

Case 1: Enumerating Values and deleting a key

If you follow the following sequence:

  • start enumerating the values collection from a thread
  • remove a key from a different thread that we have not enumerated yet
  • Continue enumerating on the original thread

The observed behavior is that the removed key will indeed be enumerated since it existed in the values collection when we started the enumeration. No exception will be raised.

Case 2: Enumerating Values and adding a key

  • start enumerating the values collection from a thread
  • add a new key from a different thread that we have not enumerated yet
  • Continue enumerating on the original thread

The observed behavior is that the added key will not be enumerated since it did not exist in values collection when we started to enumerate it. No exception will be raised whether we use TryAdd or add by assigning directly to the dictionary ie dictionary[key] = value.

Sample Code

Here is the sample program that demonstrates both cases:

ConcurrentDictionary<int, int> dictionary = new ConcurrentDictionary<int, int>();

// Seed the dictionary with some arbitrary values; 
for (int i = 0; i < 30; i++)
{
    dictionary.TryAdd(i, i);
}

// Reader thread - Enumerate the Values collection
Task.Factory.StartNew(
        () =>
        {
            foreach (var item in dictionary.Values)
            {
                Console.WriteLine("Item {0}: count: {1}", item, dictionary.Count);
                Thread.Sleep(20);
            }

        }
);

// writer thread - Modify dictionary by adding new items and removing existing ones from the end
Task.Factory.StartNew(
        () =>
        {
            for (int i = 29; i >= 0; i--)
            {
                Thread.Sleep(10);
                //Remove an existing entry 
                int removedValue;
                if (dictionary.TryRemove(i, out removedValue))
                    Console.WriteLine("Removed item {0}", removedValue);
                else
                    Console.WriteLine("Did not remove item {0}", i);

                int iVal = 50 + i*2;
                dictionary[iVal] = iVal;
                Thread.Sleep(10);
                iVal++;
                dictionary.TryAdd(iVal, iVal);
            }
        }
);

Console.ReadKey();

And here is the output in release mode:

Console output




回答2:


ConcurrentDictionary Represents a thread-safe collection of key-value pairs that can be accessed by multiple threads concurrently.

Source: MSDN



来源:https://stackoverflow.com/questions/10479867/is-concurrentdictionary-keys-or-values-property-threadsafe

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