views:

132

answers:

2

I have a seemingly very simple case where I'm using System.Threading.ReaderWriterLockSlim in the 3.5 version of the .NET Framework. I first declare one, as shown here:

Lock Declaration

I put a break point right before the lock is acquired and took a screen shot so you can see (in the watch window) that there are currently no locks held:

pre lock acquisition

Then, after calling EnterWriteLock, as you can see I am holding a Read Lock.

post lock acquisition

This seems like truly unexpected behavior and I can't find it documented anywhere. Does anyone else know why this happens? In other places in my code (earlier), this exact same line of code correctly obtains a write lock. Consistently, however, across multiple systems it instead obtains a read lock at this place in the call stack. Hope I've made this clear and thanks for taking the time to look at this.

--- EDIT---

For those mentioning asserts... this just confuses me further:

post assert

I really can't say how it got past this assertion except that perhaps the Watch Window and the Immediate window are wrong (perhaps the value is stored thread locally, as another poster mentioned). This seems like an obvious case for a volatile variable and a Happens Before relationship to be established. Either way, several lines later there is code that asserts for a write lock and does not have one. I have set a break point on the only line of code in the entire program that releases this lock, and it doesn't get called after the acquisition shown here so that must mean it was never actually acquired... right?

A: 

Can you reproduce this in a short but complete program at all?

If you add extra debugging lines, do they get printed and debugged appropriately? I wonder if your built code is out of date with your source...

Jon Skeet
I can try to reproduce it but it's odd because it does work correctly the first few times that lock is used. It's definitely not out of date, that was my first thought too. I've double and triple checked the modification date of the assemblies and I've added other features and changes that show up in the running program to be sure. If I can duplicate in a shorter app I'll try to link to it.
MKing
+2  A: 

This could be a debugger side-effect. The ReaderWriterLockSlim class is very sensitive to the current thread ID (Thread.ManagedThreadId). I can't state for a fact that the debugger will always use the current active thread to evaluate the watch expressions. It usually does, but there might be different behavior, say, if you entered the debugger with a hard break.

Trust what the code does first of all, your Debug.Assert proves the point.

Hans Passant
As mentioned, this issue only arose because my code ran into exceptions caused by not having a write lock after this line of code (without releasing the write lock in between). Passing the assertion seems to be the anomaly. It seems like non-reentrant is the preferred style for new code anyway, and that resolves the issue, so that's what I'm going with.
MKing