Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How expensive is lock(...) when the lock isn't contended?

Tags:

While looking into double-checked locking I've seen numerous recommendations to just skip the first check and immediately go for the lock and just check after taking it instead.

This lead me to wonder, is lock (this.padlock) "cheap" when uncontended?

like image 671
Johann Gerell Avatar asked Jan 09 '12 12:01

Johann Gerell


People also ask

Are locks expensive C#?

lock (Monitor. Enter/Exit) is very cheap, cheaper than alternatives like a Waithandle or Mutex.

Are locks expensive?

In fact, locks are very, very inexpensive. It's contention that's expensive. If you have to choose between a lock and contention, most of the time the lock is a better option. Locks, when used properly, are a contention avoidance mechanism.

What is lock in C#?

The lock statement acquires the mutual-exclusion lock for a given object, executes a statement block, and then releases the lock. While a lock is held, the thread that holds the lock can again acquire and release the lock. Any other thread is blocked from acquiring the lock and waits until the lock is released.


2 Answers

We can test it...

I get:

1000000000; 2164 (no lock) 1000000000; 23258 (lock) 21.094ns per lock 

Code:

using System; using System.Diagnostics;  static class P {     static void Main()     {          Test(1); // for JIT         Test(1000000);     }     static readonly object syncLock = new object();     static void Test(int count)     {         int j = 0;         var watch = Stopwatch.StartNew();         for(int i = 0 ; i < count ; i++)         {             for (int z = 0; z < 1000; z++)                 j++;         }         watch.Stop();         long withoutMillis = watch.ElapsedMilliseconds;         Console.WriteLine("{0}; {1} (no lock)", j, watch.ElapsedMilliseconds);          j = 0;         watch = Stopwatch.StartNew();         for (int i = 0; i < count; i++)         {             for (int z = 0; z < 1000; z++ )                 lock (syncLock)                 {                     j++;                 }         }         watch.Stop();         long withMillis = watch.ElapsedMilliseconds;         Console.WriteLine("{0}; {1} (lock)", j, watch.ElapsedMilliseconds);          long deltaNano = (withMillis - withoutMillis) * 1000000;                 // nano = 1000 micro = 1000000 milli         double perLockNano = deltaNano/(1000.0 * count);         Console.WriteLine("{0}ns per lock", perLockNano);     } } 
like image 89
Marc Gravell Avatar answered Sep 22 '22 12:09

Marc Gravell


According to this source, the overhead to lock and unlock is about 20ns.

like image 40
Tudor Avatar answered Sep 23 '22 12:09

Tudor