Reputation: 621
In my unsafe class below, what can be done to prevent someone from executing the unsafe method without first obtaining the lock?
class Unsafe
{
private static readonly object lockObj;
void MethodA()
{
lock (lockObj)
{
// do some things
DoUnsafeThing();
}
}
void MethodB()
{
lock (lockObj)
{
// do some things
DoUnsafeThing();
}
}
void DoUnsafeThing()
{
if (callerHasLock)
// Do the unsafe thing
else
return; // or throw some exception
}
}
Obtaining the lock again inside DoUnsafeThing()
is an option:
void DoUnsafeThing()
{
lock (lockObj)
{
// Do the unsafe thing
}
}
But DoUnsafeThing()
can now be called by threads that don't already possess the lock.
Upvotes: 2
Views: 1018
Reputation: 3399
You should be able to use Monitor.IsEntered() to verify that the thread itself has already obtained the lock:
void DoUnsafeThing()
{
if (Monitor.IsEntered(lockObj))
// Do the unsafe thing
else
return; // or throw some exception
}
You can use the Monitor
class to work with locks. In C#, the lock(...)
statement is just syntactic sugar for Monitor.Enter(o); try {...} finally {Monitor.Exit(o);}
. There are other options within it for fine-tuning. Remember, multi-threading is Hard. Know your toolset.
EDIT: (in response to framework version question update)
Prior to .NET 4.5, AFAIK the only way to handle this would be to use a thread-static Boolean alongside the synchronization object, set to true
just after entering and false
just before exiting. That same Boolean--call it callerHasLock
, to conform with your code above--can then be tested within the lock context with the same result as Monitor.IsEntered
.
Upvotes: 5