Sean
Sean

Reputation: 878

C# "lock" keyword: Why is an object necessary for the syntax?

To mark code as a critical section we do this:

Object lockThis = new Object();    
lock (lockThis)
{    
     //Critical Section
}

Why is it necessary to have an object as a part of the lock syntax? In other words, why can't this work the same:

lock
{
   //Critical Section
}

Upvotes: 7

Views: 2273

Answers (3)

Theodoros Chatzigiannakis
Theodoros Chatzigiannakis

Reputation: 29223

Because you don't just lock - you lock something (you lock a lock).

The point of locking is to disallow two threads from directly competing for the same resource. Therefore, you hide that resource behind an arbitrary object. That arbitrary object acts as a lock. When one thread enters a critical section, it locks the lock and the others can't get in. When the thread finishes its work in the critical section, it unlocks and leaves the keys out for whichever thread happens to come next.

If a program has one resource that's candidate for competing accesses, it's possible that it will have other such resources as well! But often these resources are independent from each other - in other words, it may make sense for one thread to be able to lock one particular resource and another thread in the meantime to be able to lock another resource, without those two interfering.

A resource may also need to be accessed from two critical sections. Those two will need to have the same lock. If each had their own, they wouldn't be effective in keeping the resource uncontested.

Obviously, then, we don't just lock - we lock each particular resource's own lock. But the compiler can't autogenerate that arbitrary lock object silently, because it doesn't know which resources should be locked using the same lock and which ones should have their own lock. That's why you have to explicitly state which lock protects which block (or blocks) of code.

Note that the correct usage of an object as a lock requires that the object is persistent (at least as persistent as the corresponding resource). In other words, you can't create it in a local scope, store it in a local variable and throw it away when the scope exits, because this means you're not actually locking anything. If you have one persistent object acting as a lock for a given resource, only one thread can enter that section. If you create a new lock object every time someone attempts to get in, then anyone can enter at all times.

Upvotes: 4

p.s.w.g
p.s.w.g

Reputation: 149030

Well the simple answer is that that's just how the language is specified. Locks need to have some sort of object to lock on. This allows you to control what code must be locked by controlling the scope and lifecycle of this object. See lock Statement (C# Reference).

It's possible that the designers of the language could have provided an anonymous-style lock like you've suggested, and rely on the compiler to generate an appropriate object behind the scenes. But should the object that's created be a static or instance member? How would it be used if you had multiple methods that need a lock in one class? These are difficult questions, and I'm sure the designers of the language simply didn't feel the benefit of including such a construct would be worth the added complexity or confusion it would entail.

Upvotes: 1

James Curran
James Curran

Reputation: 103535

It needs something to use as the lock.

This way two different methods can share the same lock, so only one can be used at a time.

Object lockThis = new Object();    

void read()
{
  lock (lockThis)
  {    
     //Critical Section
  }
}
void write()
{
  lock (lockThis)
  {    
     //Critical Section
  }
}

Upvotes: 3

Related Questions