The .NET ConcurrentDictionary is susceptible to a race condition that may cause unexpected data as explained at the bottom of this MSDN article. I'm assuming that there are several factors to take into account.
Q: How should I write code that is not vulnerable to that race condition that may cause data loss?
In my scenario I have an input stream that has an always increasing index (n++). My thought is that I could detect missing data if the race condition occurs and re-send it. On the other hand, there may be a better way to do this that I'm unaware of.
There is a general pitfall with concurrent collections (not limited to .net) that people have to be aware of, which is that individual operations may be thread-safe, but sequences of operations are not atomic. What I mean by this is the following: assume this scenario, where I have a concurrent collection with a Check
and an Add
operation, both atomic.
What I want to do is check if a value exists and if not, add it. So I can write this:
if(!collection.Check(value))
{
collection.Add(value);
}
Although both operations are atomic, the above sequence is not, as a thread may be interrupted between the check and the add by another thread, which leads to inconsistent results. Thus, the entire sequence should be made atomic by wrapping it in a lock
statement for example.
lock(locker)
{
if(!collection.Check(value))
{
collection.Add(value);
}
}