Reputation: 16162
The question here is: If a thread that acquiring an exclusive lock to an object –for instance by using Monitor.Enter
– is terminated, does that magically frees the exclusive lock on that object? if that is true, then suppose we call Monitor.Exit
from another thread –because we assumed that object is locked–, isn't that will throw exeption of type SynchronizationLockException
?
I am not sure it this is the expected behavior or a bug...
To demonstrate the issue, I have created a simple piece of code that calls Monitor.TryEnter without calling Monitor.Exit
at System.Timers.Timer.Elapsed event callback "Note that the Timers.Timer class uses internally ThreadPool
to run the callback event handler, and it may calls the elapsed callback each time on a different thread from the pool.."
class Foo
{
private System.Timers.Timer _timer = new System.Timers.Timer(2000);//every 2s
private static readonly object _locker = new object();//static locker object
public Foo()
{
_timer.Elapsed += delegate
{
if (Monitor.TryEnter(_locker))//acquiring the lock without calling Exit..
{
Console.WriteLine(string.Format("Access Succeed!!, Thread Id {0}",
Thread.CurrentThread.ManagedThreadId));
Thread.Sleep(6000);//simulate a work for 6 seconds
}
else
{
Console.WriteLine(string.Format("Unable to access to locker method within locker object, Thread Id {0}",
Thread.CurrentThread.ManagedThreadId));
}
};
_timer.Start();
}
}
//to test: just initialize a new instance of foo class
Foo foo = new Foo();
//blocks until application is terminated..
Thread.Sleep(Timeout.Infinite);
Results at output window shows:
Access Succeed!!, Thread Id 11
Unable to access to locker method within locker object, Thread Id 12
Unable to access to locker method within locker object, Thread Id 12
Access Succeed!!, Thread Id 11
Unable to access to locker method within locker object, Thread Id 12
Unable to access to locker method within locker object, Thread Id 12
Unable to access to locker method within locker object, Thread Id 12
Unable to access to locker method within locker object, Thread Id 12
Access Succeed!!, Thread Id 11
Unable to access to locker method within locker object, Thread Id 12
Unable to access to locker method within locker object, Thread Id 12
....
Upvotes: 1
Views: 1208
Reputation: 273274
What you are seeing is that multiple calls to TryEnter from the same thread will succeed.
This is called re-entrancy and is usually used for recursive calls. You are using it a little strange, that's all.
If a thread that acquiring an exclusive lock to an object –for instance by using Monitor.Enter– is terminated, does that magically frees the exclusive lock on that object?
Alas, no.
That's why you should always combine TryEnter()
with a try/finally to execute the Exit()
Upvotes: 2
Reputation: 887479
No threads are being terminated here.
Rather, they're returned to the threadpool, only to be reused by later timer events.
Monitor.Enter
is re-entrant; entering a lock twice on the same thread will not block.
Upvotes: 2