Why SynchronizedCollection<T>
does not acquire a lock on SyncObj in explicit implementation of IEnumerable.GetEnumerator()
IEnumerator IEnumerable.GetEnumerator()
{
return this.items.GetEnumerator();
}
Implicit implementation does acquire a lock on SyncOb (verified by reflector).
It could be开发者_如何转开发 problem during foreach loop on this collection. One thread might have acquired a lock and the other could try to read it using foreach?
Because there is no way for the class to know when the client code is done using the iterator. Which is one reason that the MSDN Library docs on the System.Collection classes always warn that iterating a collection isn't thread-safe.
Although they appeared to have forgotten to mention that in the article for SynchronizedCollection. The irony...
Modifying the collection while someone's using an iterator is a concurrency violation anyway.
What would your alternative be? Lock the collection when the iterator is acquired, and not unlock it until the iterator is destructed?
I'm going to go ahead and say that this could be a bug (ed: or at least an inconsistency) in the implementation. Reflector shows exactly what you're seeing, that every other explicit implementation calls lock on the SyncRoot
given, except for IEnumerable.GetEnumerator()
.
Perhaps you should submit a ticket at Microsoft Connect.
I believe the reason the implicit GetEnumerator()
method calls lock
is because List<T>.GetEnumerator()
creates a new Enumerator<T>
which relies on the private field _version
on the list. While I agree with the other posters, that I don't see the use in locking the GetEnumerator()
call, but since the constructor of Enumerator<T>
relies on non-threadsafe fields, it would make sense to lock. Or at least remain consistent with the implicit implementations.
精彩评论