what happens with lock when thread gets closed while the lock is set
I was wondering, If in a thread i have a lock statement and if that specific thread is closed while the lock is set, what happens with the lock ?
Are the other threads going to have access to the critic开发者_JS百科al zone(does my specific lock variable get unlocked) or does the lock remain active and bricks my app ? If so, What solutions do i have to avoid the brick?
A lock statement:
lock (x)
{
...
}
is interpreted by the compiler in the resulting IL to:
Monitor.Enter(x);
try
{
...
}
finally
{
Monitor.Exit(x);
}
So as you can see if an exception is thrown, the lock is released because of the finally
statement. So even if you terminate the thread with Thread.Abort (which causes a ThreadAbortException to be thrown inside the thread) which you should ABSOLUTELY NEVER do, the lock will be released.
A ThreadAbortException gets thrown which most of the time as Darin above has stated will result in the finally block being run which will release the lock.
But...
There are scenarios where this will not happen. The most common of which is if a NOP is inserted between the try & the finally by the compiler. If this occurs and the exception occurs at that particular point in time then the lock will become orphaned resulting in a deadlock scenario.
You should never terminate(for example Thread.Abort or even worse raw winapi calls) a thread from the outside without unloading the app-domain afterwards, so this doesn't matter in practice. To terminate a thread set some kind of flag which the thread checks and then gracefully exits.
If you use Thread.Abort
an asynchronous exception gets thrown, so the lock will be cleaned up if it's released in a finally clause(this is the case with the lock
statement). But asynchronous exceptions easily corrupt state unless the code has been carefully with them in mind, so they should be avoided.
MSDN on ThreadAbortException
:
When a call is made to the Abort method to destroy a thread, the common language runtime throws a ThreadAbortException. ThreadAbortException is a special exception that can be caught, but it will automatically be raised again at the end of the catch block. When this exception is raised, the runtime executes all the finally blocks before ending the thread. Because the thread can do an unbounded computation in the finally blocks or call Thread.ResetAbort to cancel the abort, there is no guarantee that the thread will ever end. If you want to wait until the aborted thread has ended, you can call the Thread.Join method. Join is a blocking call that does not return until the thread actually stops executing.
If you use raw winapi to abort a thread you're pretty much out of luck and should terminate the process as well.
About the only reason to acquire a lock is so that you can change the state of an object and not have other threads see it in an invalid state. If something forcibly releases that lock before the state is restored to valid, the next thread to acquire the lock will blow up when it accesses the inconsistent state.
Think of, for example, the pointers in a doubly-linked list. What if the closed thread modified a forward pointer but not the corresponding back pointer? If you don't have code to cleanly close the thread, you are screwed whether the lock is automatically release or not. (If it is released, the next thread to acquire it will blow up when it accesses the broken pointers. If it not released, every thread to try to acquire it will hang.)
If you do have code to cleanly close the thread, surely it will also release the lock. So if this is your issue, you're doing something else wrong.
精彩评论