8

I have the following situation: I want to mutualy exclude access to an object.

So far I normaly would use a lock object

object lockObject = new object();
...

method1: lock(lockObject) { CODE1 }

Now I have also a method which can be called from another thread. It should not be blocked for unknown time, instead it should give an answer in a defined time.

In this case i would use a monitor, like

method2:
try{
   Monitor.TryEnter(lockObject , 20000, ref lockTaken);
   if (lockTaken) {CODE2}
}
catch(...){...}
finally
{
   if (lockTaken) Monitor.Exit(timerLock);
}

Now my question is: can lock and monitor be mixed in such a way if the lockobject is the same and mutually exclude each other, or would it be needed to change every lock to a monitor.

So would both times the same token be "locked", or would the monitor create another token for the object then the lock?

At a glimpse I cannot see that the aplication runs in code of both at the same time. But I don't know if any timing issues can exist, where CODE1 and CODE2 are executed in parallel.

1
  • 1
    I feel your pain; I often wish the lock keyword took a timeout somehow Commented Jan 17, 2013 at 11:01

2 Answers 2

9

can lock and monitor be mixed in such a way if the lockobject is the same and mutually exclude each other

Yes, that is totally safe and it will work.

The lock { } statement is rewritten to calls to Monitor.Enter() and Monitor.Exit(). It's just short-hand, very similar to the using() {} statement.

From MSDN:

 lock (x) ...

becomes

System.Threading.Monitor.Enter(x);
try {
   ...
}
finally {
   System.Threading.Monitor.Exit(x);
}

And as per the comment, in Fx4 and later it can use Monitor.TryEnter() . But the simple version above answers your question.

1
  • 3
    Or Monitor.TryEnter when targeting .NET 4+.
    – Jon Skeet
    Commented Jan 17, 2013 at 10:51
7
lock (sync)
{
   return World();
}

Would look along the lines of this in Intermediate Language.

L_0007: call void [mscorlib]System.Threading.Monitor::Enter(object)
L_000c: call int32 Hello::World()
L_0011: stloc.0 
L_0012: leave.s L_001b
L_0014: ldloc.1 
L_0015: call void [mscorlib]System.Threading.Monitor::Exit(object)

So it should be okay. They are technically equivalent.

2
  • note that recent versions of csc, when targeting .NET 4 or above, will have different IL to this Commented Jan 17, 2013 at 11:00
  • Thanks, true. Just did it for rough illustration. Commented Jan 17, 2013 at 11:04

Not the answer you're looking for? Browse other questions tagged or ask your own question.