lock inside lock
I'm wondering if this construction will cause an error:
lock(sync)
{
// something
lock(sync)
{
//something
lock(sync)
{
//something
}
}
}
I've run this code, and it seems fine, but maybe in some circumstances an error may be thrown?
Solution 1:
lock
is a wrapper for Monitor.Enter
and Monitor.Exit
:
The
lock
keyword callsEnter
at the start of the block andExit
at the end of the block. From the former's documentation:
From the documentation for Monitor.Enter
:
It is legal for the same thread to invoke
Enter
more than once without it blocking; however, an equal number ofExit
calls must be invoked before other threads waiting on the object will unblock.
Because the calls to Enter
and Exit
are paired, your code pattern has well defined behaviour.
Note, however, that lock
is not guaranteed to be an exception-less construct:
A
ThreadInterruptedException
is thrown ifInterrupt
interrupts a thread that is waiting to enter alock
statement.
Solution 2:
To explain why it is well-defined behavior and will never fail:
Aside: This answer has better details about how locks actually work
The lock occurs at the Thread
level, so calling it a second time on the same thread will be redundant. I would think it would not have any performance penalty (although that would depend on how exactly the internals of .Net are written, so I can't guarantee that)
Many times you'd have a public function that calls another public function in your class, whom both need the lock when used seperately. If this was not allowed the following would fail:
private Dictionary<string, int> database = new Dictionary<string, int>();
private object databaseLock = new object();
public void AddOrUpdate(string item)
{
lock (databaseLock)
{
if (Exists(item))
database.Add(item, 1);
else
++database[item];
}
}
public bool Exists(string item)
{
lock (databaseLock)
{
//... Maybe some pre-processing of the key or item...
return database.ContainsKey(item);
}
}