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.