So your code is executing Dictionary.FindEntry
. It’s not a deadlock – a deadlock happens when two threads block in a way which makes them wait for one another to release a resource, but in your case you’re getting two seemingly infinite loops. The threads aren’t locked.
Let’s take a look at this method in the reference source:
private int FindEntry(TKey key) {
if( key == null) {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
if (buckets != null) {
int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
for (int i = buckets[hashCode % buckets.Length]; i >= 0; i = entries[i].next) {
if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) return i;
}
}
return -1;
}
Take a look at the for
loop. The increment part is i = entries[i].next
, and guess what: entries
is a field which is updated in the Resize
method. next
is a field of the inner Entry
struct:
public int next; // Index of next entry, -1 if last
If your code can’t exit the FindEntry
method, the most probable cause would be you’ve managed to mess the entries in such a way that they produce an infinite sequence when you’re following the indexes pointed by the next
field.
As for the Insert
method, it has a very similar for
loop:
for (int i = buckets[targetBucket]; i >= 0; i = entries[i].next)
As the Dictionary
class is documented to be non-threadsafe, you’re in the realm of undefined behavior anyway.
Using a ConcurrentDictionary
or a locking pattern such as a ReaderWriterLockSlim
(Dictionary
is thread-safe for concurrent reads only) or a plain old lock
nicely solves the problem.