Is the following code thread safe?
var dict = new Dictionary<int, string>()
{ { 0, "" }, { 1, "" }, { 2, "" }, { 3, "" } };
var nums = dict.Keys.ToList();
Parallel.ForEach(nums, num =>
{
dict[num] = LongTaskToGenerateString();
});
return dict;
No, Dictionary<TKey, TValue>
class is not thread-safe for modification, as can be seen in the documentation:
A
Dictionary<TKey, TValue>
can support multiple readers concurrently, as long as the collection is not modified. Even so, enumerating through a collection is intrinsically not a thread-safe procedure. In the rare case where an enumeration contends with write accesses, the collection must be locked during the entire enumeration. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization.
In your case, if some threads will finish the LongTaskToGenerateString
almost simultaneously their dictionary updates will interference.
You might either use the SyncRoot
property to synchronize the access manually, or just take the ConcurrentDictionary<TKey, TValue>
class, as suggested by asawyer in the comments.
This implementation suggests that if you're only updating the values for existing keys, it should be OK (looking also at this) - the inelegant effect could be inaccurate value of the version
property. It is used to guard against modifying the collection while it's being enumerated, so it doesn't really matter at which value it will end up. Don't know about any guarantees about this though.
It appears as though your dictionary is only for use as a return value, and is never actually used to look up keys. In that case, you don't even need the dictionary until you've computed all the final output values.
So you can use PLINQ for this:
var nums = new[] { 0, 1, 2, 3 };
var dict = nums.AsParallel()
.Select(num => new KeyValuePair<int, string>
(num, LongTaskToGenerateString(num)));
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
return dict;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With