I just realized that in some place in my code I have the return statement inside the lock and sometime outside. Which one is the best?
1)
void exampl
It doesn't make any difference; they're both translated to the same thing by the compiler.
To clarify, either is effectively translated to something with the following semantics:
T myData;
Monitor.Enter(mutex)
try
{
myData= // something
}
finally
{
Monitor.Exit(mutex);
}
return myData;
For what it's worth, the documentation on MSDN has an example of returning from inside of the lock. From the other answers on here, it does appear to be pretty similar IL but, to me, it does seem safer to return from inside the lock because then you don't run the risk of a return variable being overwritten by another thread.
Note: I believe this answer to be factually correct and I hope that it is helpful too, but I'm always happy to improve it based on concrete feedback.
To summarize and complement the existing answers:
The accepted answer shows that, irrespective of which syntax form you choose in your C# code, in the IL code - and therefore at runtime - the return
doesn't happen until after the lock is released.
return
inside the lock
block therefore, strictly speaking, misrepresents the flow of control[1], it is syntactically convenient in that it obviates the need for storing the return value in an aux. local variable (declared outside the block, so that it can be used with a return
outside the block) - see Edward KMETT's answer.Separately - and this aspect is incidental to the question, but may still be of interest (Ricardo Villamil's answer tries to address it, but incorrectly, I think) - combining a lock
statement with a return
statement - i.e., obtaining value to return
in a block protected from concurrent access - only meaningfully "protects" the returned value in the caller's scope if it doesn't actually need protecting once obtained, which applies in the following scenarios:
If the returned value is an element from a collection that only needs protection in terms of adding and removing elements, not in terms of modifications of the elements themselves and/or ...
... if the value being returned is an instance of a value type or a string.
In any other case, the locking must be performed by the caller, not (just) inside the method.
[1] Theodor Zoulias points out that that is technically also true for placing return
inside try
, catch
, using
, if
, while
, for
, ... statements; however, it is the specific purpose of the lock
statement that is likely to invite scrutiny of the true control flow, as evidenced by this question having been asked and having received much attention.
[2] Accessing a value-type instance invariably creates a thread-local, on-the-stack copy of it; even though strings are technically reference-type instances, they effectively behave like-value type instances.