what's wrong with lock(this) ?

  • Thread starter Thread starter n_o_s_p_a__m
  • Start date Start date
N

n_o_s_p_a__m

I have seen some debate but am not clear on what the problematic
implications of the expression lock(this) are. Microsoft seems to
advocate it, but others seem to be against it.

Pros and cons?

-KJ
 
(e-mail address removed) (n_o_s_p_a__m) wrote in
I have seen some debate but am not clear on what the problematic
implications of the expression lock(this) are. Microsoft seems to
advocate it, but others seem to be against it.

Pros and cons?

lock() is most of the time used as a semaphore for a critical
action. To prevent multiple threads entering the same codeblock, an object
is locked (the parameter to lock()). THe bigger the object, the more time
it costs to lock it. So if you just want to prevent multiple threads
entering a codeblock, you'd better do this:

object uniqueObject = new object();

lock(uniqueObject)
{
// your code
}

Frans.
 
Frans Bouma said:
(e-mail address removed) (n_o_s_p_a__m) wrote in


lock() is most of the time used as a semaphore for a critical
action. To prevent multiple threads entering the same codeblock, an object
is locked (the parameter to lock()). THe bigger the object, the more time
it costs to lock it. So if you just want to prevent multiple threads
entering a codeblock, you'd better do this:

object uniqueObject = new object();

lock(uniqueObject)
{
// your code
}

While I agree with the idea of using a separate object, I disagree with
your reasoning. In particular, I don't know of anything which makes it
slower to lock a bigger object.

The main reason (IMO) for avoiding locking on "this" is in case other
classes are locking on the same reference. As soon as you lock on a
reference which other classes have access to, you're at the whim of
what those classes will be doing in terms of deadlocking etc. If you
only ever lock on references which are only available within your own
class, you get a lot more control. You can also have different locks
separate "partitions" of exclusion.
 
Frans Bouma said:
(e-mail address removed) (n_o_s_p_a__m) wrote in


lock() is most of the time used as a semaphore for a critical
action. To prevent multiple threads entering the same codeblock, an object
is locked (the parameter to lock()). THe bigger the object, the more time
it costs to lock it. So if you just want to prevent multiple threads
entering a codeblock, you'd better do this:

I don't think thats entirely correct. Nothing I have seen suggests that
lock\Monitor has any issue with object size. Instead Monitor basically uses
a small SyncBlock which is associated with the object on the fly. the
parameter passed to lock\Monitor.Enter() is simply the one which has the
associated SyncBlock so that further calls to lock\Monitor.Enter() can find
that block and handle it. I think the block is disassociated when all lock
blocks end(this is mostly based on my own examiniation of rotor and Jeffery
Richter's column Safe Thread Synchronization[1], so I could easily be
wrong).

I would be interested if you happen to have information as to why object
size matters, however.

The more important reason, IMHO, not to lock on this is that this is
available to other objects. If you have a method that locks on this, a
method in another object(on a different thread) could easily call
lock(myObjectInstanceVariable), thereby creating a potential deadlock in a
very unrelated piece of code. Anytime you perform a lock on a value that is
available to the outside you run the risk of it being locked by code outside
of your control and introducing a deadlock.

1. http://msdn.microsoft.com/msdnmag/issues/03/01/NET/
 
Frans,
its not really that it costs mroe to lock bigger objects its to
prevent deadlocks with opened monitors on the object and the finalizers,
in the case that the monitor never exits before the object is ready for
finalization
HTH
 
n_o_s_p_a__m said:
I have seen some debate but am not clear on what the problematic
implications of the expression lock(this) are. Microsoft seems to
advocate it, but others seem to be against it.

Pros and cons?

I haven't seen any major arguments about lock( this) - the only problem
I see with it is that the lock potentially has a larger 'granularity'
than might really be needed.

For example, if an object contains an internal cache and some other
value that is unrelated to the cache, and both the cache and the value
can be updated in multiple threads, there's probably no reason to lock
on the entire object when updating the cache - you can lock on the cache
alone.

However, I have seen some discussion on the "lock( typeof( ClassName))"
idiom, indicating that it should not be used (even though it is used in
many Microsoft samples). See:

http://msdn.microsoft.com/library/en-us/dnaskdr/html/askgui06032003.asp
 
mikeb said:
However, I have seen some discussion on the "lock( typeof( ClassName))"
idiom, indicating that it should not be used (even though it is used in
many Microsoft samples). See:

http://msdn.microsoft.com/library/en-us/dnaskdr/html/askgui06032003.asp

The same arguments presented apply to "this" as well:

<quote>
The basic problem here is that you don't own the type object, and you
don't know who else could access it. In general, it's a very bad idea
to rely on locking an object you didn't create and don't know who else
might be accessing. Doing so invites deadlock. The safest way is to
only lock private objects.
</quote>
 
While I agree with the idea of using a separate object, I disagree with
your reasoning. In particular, I don't know of anything which makes it
slower to lock a bigger object.

The main reason (IMO) for avoiding locking on "this" is in case other
classes are locking on the same reference. As soon as you lock on a
reference which other classes have access to, you're at the whim of
what those classes will be doing in terms of deadlocking etc. If you
only ever lock on references which are only available within your own
class, you get a lot more control. You can also have different locks
separate "partitions" of exclusion.

I re-read the thread on developmentor and I confused two things,
which caused my error. I stand corrected :)

Frans.
 
Back
Top