开发者

how can a lock statement exit without releasing the lock?

I have a strange 开发者_运维知识库problem, a deadlock problem, where if I pause the program using Visual Studio and inspect the threads I can only see two threads waiting on the lock. No thread appears to be inside the lock scope! Is Visual Studio just lying or how can a lock statement exit without releasing the lock?

Thanks


This can happen under the following circumstances. Suppose you have

Enter();
try
{
   Foo();
}
finally
{
   Exit();
}

and a thread abort exception is thrown after the Enter but before the try. Now the monitor has been entered but the finally will never run because the exception was thrown before the try.

We've fixed this flaw in C# 4. In C# 4 the lock statement is now generated as

bool mustExit = false;
try
{
    Enter(ref mustExit);
    Foo();
}
finally
{
    if (mustExit) Exit();
}

Things can still go horribly wrong of course; aborting a thread is no guarantee that the thread ever aborts, that finally blocks ever run, and so on. You could end up in the unhandled exception event handler with the lock still taken. But this is at least a little better.


This can happen if you manually call Monitor.Enter(something) without calling Monitor.Exit.


Do you have any explicit calls to Monitor.Enter / Monitor.TryEnter in your code? Can you see the stack traces for those waiting threads? If so, look at where they're waiting - that should make it obvious.


Are you by any chance calling yield return from within a lock statement from a thread pool thread?

If that is the case, you may want to look at Yielding surprises

This blog post describes a bug (I got locked out) I encountered when I combined those three things the wrong way. Luckly I was albe to resolve the issue with a small change to the code.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜