1

I was recently asked by a friend of mine who's just starting to play around with threading what the difference between using a secondary object purely for the purpose of locking or just locking the object you're referencing is. I had to admit that I had no idea, can anyone tell me? I will try and demonstrate with a couple of code snippets:

First method:

List<string> data = new List<string>();
object datalock = new object();

void main()
{
    lock(datalock)
    {
        if (data.contains("SomeSearchString"))
        {
            //Do something with the data and then remove it
        }
    }
}

Second method:

List<string> data = new List<string>();

void main()
{
    lock(data)
    {
        if (data.contains("SomeSearchString"))
        {
            //Do something with the data and then remove it
        }
    }
}

Is there a significant difference or is this down to personal coding style? If there is a significant difference, can anyone explain what it is?

I did come across another question [Difference between lock(locker) and lock(variable_which_I_am_using)] in which the answer implied that both of these are equivalent, but if that's the case, which would be the best to use and why?

I've seen a number of examples scattered around the net, I tend to use the first method as a matter of personal choice, but I wondered what the merits of using the second method would be.

Community
  • 1
  • 1
BenAlabaster
  • 39,070
  • 21
  • 110
  • 151

4 Answers4

5

The big difference is that with a secondary object that only your code knows about there is no risk of unexpected consequences (deadlocks, pulse/wait gotchas, etc) from other code (not yours) locking against the primary object (which is commonly available to other code).

IMO, perhaps the CLR team would have done better with an explicit Lock type - or maybe Monitor should have been non-static, etc.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • I was just typing that... The only thing I was going to add was that locking on the primary object does allow subclasses that know what they are doing to participate in the superclasses locking strategy, which gives slightly more flexibility - but at the risk that consumers that don't know what they are doing can cause additional problems. – Bill Michell Apr 27 '09 at 22:16
1

The most important point has been covered by Marc, but I prefer the first pattern because it also opens up scope for having separate objects for read and write locks or any other level of granularity that may be useful for your specific use.

Martin Harris
  • 28,277
  • 7
  • 90
  • 101
  • I guess it also allows for child methods of the target object to still be accessed while the lock is placed instead of having to wait for the lock to be released... – BenAlabaster Apr 27 '09 at 22:27
0

Fundamentally, there is no difference. If all thread-unsafe operations lock on the same object, there is no difference. However, from an implementation perspective there can be differences. If other threads need access to the object where an exclusive lock would be required, you have to ensure that you make that sync object available and make it clear which object needs to be locked.

On the other hand, there are some instances where you might actually assign the value to something different within your lock block. In this case, you'd obviously need to lock on an unrelated object.

It comes down to both personal preference and maintainability (is locking on a second object required, a bad idea, or neither?)

Adam Robinson
  • 182,639
  • 35
  • 285
  • 343
0

Using different object to lock allows more synchronization granularity and performance. If you are locking on the same object, one operation may be blocking another one needlessly. If you use lock(this), all of the concurrent operations have to wait until the one that has the lock releases it. However, this may not be necessary as some of the operations may not be accessing the same resources. So you're locking them needlessly and therefore hurting the performance. Instead, use different synchronization objects for different groups of shared resources and have your operations use the corresponding lock for the resource that they need to access.

Mehmet Aras
  • 5,284
  • 1
  • 25
  • 32