C# Language lock


Example

lock provides thread-safety for a block of code, so that it can be accessed by only one thread within the same process. Example:

private static object _lockObj = new object();
static void Main(string[] args)
{
    Task.Run(() => TaskWork());
    Task.Run(() => TaskWork());
    Task.Run(() => TaskWork());

    Console.ReadKey();
}

private static void TaskWork()
{
    lock(_lockObj)
    {
        Console.WriteLine("Entered");

        Task.Delay(3000);
        Console.WriteLine("Done Delaying");

        // Access shared resources safely

        Console.WriteLine("Leaving");
    }   
}

Output:

Entered
Done Delaying
Leaving
Entered
Done Delaying
Leaving
Entered
Done Delaying
Leaving

Use cases:

Whenever you have a block of code that might produce side-effects if executed by multiple threads at the same time. The lock keyword along with a shared synchronization object (_objLock in the example) can be used to prevent that.

Note that _objLock can't be null and multiple threads executing the code must use the same object instance (either by making it a static field, or by using the same class instance for both threads)

From the compiler side, the lock keyword is a syntactic sugar that is replaced by Monitor.Enter(_lockObj); and Monitor.Exit(_lockObj);. So if you replace the lock by surrounding the block of code with these two methods, you would get the same results. You can see actual code in Syntactic sugar in C# - lock example