In the .NET Framework, there is Dictionary
and ConcurrentDictionary
.
These provide method like Add
, Remove
, and so on...
I know when we design a multi-thread program, we use ConcurrentDictionary
to replace Dictionary
for thread-safety.
I wonder why ConcurrentDictionary
has AddOrUpdate
, GetOrAdd
and similar methods, while Dictionary
has not.
We always like below code to get object from a Dictionary
:
var dict = new Dictionary<string, object>();
object tmp;
if (dict.ContainsKey("key"))
{
tmp = dict["key"];
}
else
{
dict["key"] = new object();
tmp = new object();
}
but when using ConcurrentDictionary
, similar code is just one line only.
var conDict = new ConcurrentDictionary<string, object>();
var tmp = conDict.GetOrAdd("key", new object());
I expect .NET to have those methods, but why it doesn't?
Represents a thread-safe collection of key/value pairs that can be accessed by multiple threads concurrently.
The GetOrAdd function The vast majority of methods it exposes are thread safe, with the notable exception of one of the GetOrAdd overloads: TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory); This overload takes a key value, and checks whether the key already exists in the database.
It is thread safe in your usage. It becomes not thread safe when the delegate passed to AddOrUpdate has side effects, because those side effects may be executed twice for the same key and existing value.
ConcurrentDictionary is thread-safe collection class to store key/value pairs. It internally uses locking to provide you a thread-safe class. It provides different methods as compared to Dictionary class. We can use TryAdd, TryUpdate, TryRemove, and TryGetValue to do CRUD operations on ConcurrentDictionary.
Because such methods are:
A bare minimum for working in a concurrent context. You can't split the Get
and Add
in two separate steps without locking, and still yield correct results.
When implemented for Dictionary<TKey, TValue>
, it implicitly indicates some level of thread-safety, as if Dictionary<TKey, TValue>
can handle this in a correct matter. It can't, so it is just not implemented. That doesn't stop you for making an extension method to do something similar.
public static TValue GetOrAdd<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, Func<TKey, TValue> valueGenerator)
{
//
// WARNING: this method is not thread-safe and not intended as such.
//
if (!dict.TryGetValue(key, out TValue value))
{
value = valueGenerator(key);
dict.Add(key, value);
}
return value;
}
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