Reputation: 26338
I'm working on a concurrent dictionary implementation for C#, and I'm wondering if this GetEnumerator()
implementation is actually (thread) safe.
It's not doing a actual snapshot, so I'm wondering if it'll mess up later read/writes to the internal dictionary, or if it'll expose potential deadlocks because the enumeration of the exposed IEnumerator
will actually run inside the lock.
private readonly Dictionary<TKey, TValue> internalDictionary;
private SpinLock spinLock = new SpinLock();
IEnumerator IEnumerable.GetEnumerator()
{
IEnumerator enumerator;
bool lockTaken = false;
try
{
spinLock.TryEnter(ref lockTaken);
enumerator = (this.internalDictionary as IEnumerable).GetEnumerator();
}
finally
{
if (lockTaken)
{
spinLock.Exit(false);
}
}
return enumerator;
}
Upvotes: 2
Views: 2167
Reputation: 171188
Your method is not thread-safe with respect to concurrent writers because
ToList
on it or something to actually snapshot.Here is a fixed version with all the cleverness removed:
IEnumerator IEnumerable.GetEnumerator()
{
lock (internalDictionary) return internalDictionary.ToList();
}
Concurrent writers have to take the lock, too.
Upvotes: 3
Reputation: 9474
The first things that springs to mind is why on earth you would want to create such a beast yourself when .NET ships with thread-safe concurrent collection classes (including a dictionary). Google System.Collections.Concurrent
for more information.
I've previously benchmarked the ConcurrentDictionary class and I'll guarantee you that they are significantly faster than anything you could write yourself, even when using spin locks or Interlocked to avoid any of the heavier locking mechanisms.
In answer to your question, maybe, but it depends on the implementation (which is never a good thing). I'd guess that any write attempts would fail, since the standard collection classes cannot be modified while being iterated; but I wouldn't rely on any such mechanism to keep my own code safe.
Upvotes: 1