Will lock() statement block all threads in the process/appdomain?

Maybe the question sounds silly, but I don’t understand ‘something about threads and locking and I would like to get a confirmation (here’s why I ask).

So, if I have 10 servers and 10 request in the same time come to each server, that’s 100 request across the farm. Without locking, thats 100 request to the database.

If I do something like this:

private static readonly object myLockHolder = new object();
if (Cache[key] == null)
{
   lock(myLockHolder)
   {
      if (Cache[key] == null)
      {
         Cache[key] = LengthyDatabaseCall();
      }
   }
}

How many database requests will I do? 10? 100? Or as much as I have threads?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You have a hierarchy of objects:

  • You have servers (10)
  • On each server you have processes (probably only 1 – your service/app pool)
  • In each process you have threads (probably many)

Your code will only prohibit threads within the same process on the same server access to modify the Cache object simultaneously. You can create locks across processes and even across servers, but the cost increases a lot as you move up the hierarchy.

Using the lock statement does not actually lock any threads. However, if one thread is executing code inside the lock (that is in the block of code following the lock statement) any other thread that wants to take the lock and execute the same code has to wait until the first thread holding the lock leaves the block of code and releases the lock.

The C# lock statement uses a Windows critical section which a lightweight locking mechanism. If you want to lock across processes you can use a mutex instead. To lock across servers you can use a database or a shared file.

As dkackman has pointed out .NET has the concept of an AppDomain that is a kind of lightweight process. You can have multiple AppDomains per process. The C# lock statement only locks a resource within a single AppDomain, and a proper description of the hierarchy would include the AppDomain below the process and above the threads. However, quite often you only have a single AppDomain in a process making the distinction somewhat irrelevant.

Method 2

The C# lock statement locks on a particular instance of an object (the object you created with new object()). Objects are (in most cases) not shared across AppDomains, thus if you are having 10 servers, 10 threads can run concurrently access your database with that piece of code.

Method 3

Lock is not blocking threads.
It is locking some instance of an object. And each thread which tries to access it is blocked.
So in your case each thread which will try to access myLockHolder will be locked and not all the threads.
In other words we can say that Lock statement is syntactic sugar for using Critical Section.

Like you can see in MSDN :

lock(expression) statement block

where:

expression Specifies the object that you want to lock on. expression must
be a reference type. Typically,
expression will either be this, if you
want to protect an instance variable,
or typeof(class), if you want to
protect a static variable (or if the
critical section occurs in a static
method in the given class).

statement block The statements of the critical section.

Method 4

lock will block all threads in that application from accessing the myLockHolder object.

So if you have 10 instances of the application running you’ll get 10 requests to the server while the object is locked on each. The moment you exit the lock statement, the next request will process in that application, but as long as Cache[key] is not null, it won’t access the database..

The number of actual requests you get depends on what happens here:

  if (Cache[key] == null)
  {
     Cache[key] = LengthyDatabaseCall();
  }

If LengthyDatabaseCall(); fails, the next request will try and access the database server and retrieve the information as well, so really your best case scenario is that there will only be 10 requests to the server.

Method 5

Only the threads that need access to your shared variable at the moment another thread is using it will go into a wait state.

how many that is at any give time is hard to determine.

Method 6

Your DB will get 10 requests, with odds being good that requests 2-10 run much faster than request 1.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x