Weird title? Not really. I’ve said before that multi-threading programming is hard and despite advances in programming languages and libraries I still think we haven’t reached a comfortable point yet. Meanwhile the desktop processor market is moving towards multiple cores and only slight adjustments in the clock speed so it makes a lot of sense to make your apps multi-thread-able (if problem domain permits, that is).
While working on my highly asynchronous P2P core, I noticed a weird thing – the debugger would complain here and there that a collection was changed while iterating through it, even though I’ve protected all access to a given collection with a lock. Here’s a code sample:
lock(coll.SyncRoot)
{
foreach(SomeObj so in coll)
so.SomeMethod();
}
I double-checked that:
- coll is a private member of a class it belongs to and is not exposed in any way to the outside world
- all method calls that have code like above are being called from different threads (generally a random thread from a thread pool)
- all access to coll is protected with a lock
So what could be the problem? Well, turns out I did not really check the second bullet right. It was from the SomeMethod that I called back into a class that contained coll and unfortunately into one of few methods that modify coll, so the debugger was right (as usual). So when I called SomeMethod, it (sometimes, rarely – that’s why it was hard to spot) called another method which tried to acquire the same coll.SyncRoot lock, I am still on the same thread from which I already acquired the lock and the lock succeeds – collection gets modified and on the next MoveNext (iteration step) the debugger throws an exception.
The moral of the story – beware of reentrancy of locks and always double, hell, triple check the second bullet.
Be the first to rate this post
- Currently 0/5 Stars.
- 1
- 2
- 3
- 4
- 5