Lock statement can be really useful when you are writing multithreaded applications. Basically what lock statement does is it monitors and prevents some particular blocks of code from being accessed simultaneously by multiple threads.

It's always good to go by an example. First, we are creating a very simple multithreaded application without any lock statements. We are having a class there named “MyClass” which will have a single method.
public class MyClass
{
    public void MyMethodWithoutLock()
    {
        Thread.Sleep(5000);
        Console.WriteLine("Without Lock " + DateTime.Now);
    }
}
Inside the above method, let’s assume that we are doing some time-consuming work and then printing out a message with the current time.

Inside the Main method, let's create an object of “MyClass” and call the “MyMethodWithoutLock” from different threads.
class Program
{
    static void Main(string[] args)
    {
        MyClass oMyClass = new MyClass();
        List<Thread> threads = new List<Thread>();
 
        for (int i = 0; i < 5; i++)
        {
            Thread t = new Thread(oMyClass.MyMethodWithoutLock);
            threads.Add(t);
        }
 
        foreach (Thread t in threads)
        {
            t.Start();
        }
 
        Console.WriteLine(DateTime.Now);
    }
}

Here there is nothing complex, just some very simple multithreading. We have created an object of "MyClass" and created a variable to hold a list of threads. Then added five threads to threads list which will call the “MyMethodWithoutLock” of the only object “oMyClass”. Finally, we are starting all the threads at once and printing out the current time. Please note that in the Main method is only a single object of “MyClass”.

So the output is as follows.
Pic1
Without Lock

As you can see after starting the threads at 11:35:01, all the threads have completed calling “MyMethodWithoutLock” simultaneously at 11:35:06. So the point here is all threads have been calling “MyMethodWithoutLock” at the same time which is a perfect concurrency.

Now let’s say we have a scenario where we have two methods. One method should be called simultaneously and the other should not be called simultaneously. For this, we can use the lock statement and let’s see how.

Hers is the modified class.
public class MyClass
{
    private Object thisLock = new Object();
 
    public void MyMethodWithoutLock()
    {
        Thread.Sleep(5000);
        Console.WriteLine("Without Lock " + DateTime.Now);
    }
 
    public void MyMethodWithLock()
    {
        lock (thisLock)
        {
            Thread.Sleep(5000);
            Console.WriteLine("With Lock " + DateTime.Now);
        }
    }
}
Inside Main, we have some threads as previous. The only difference is threads will be calling both methods as below.
class Program
{
    static void Main(string[] args)
    {
        MyClass oMyClass = new MyClass();
        List<Thread> threads = new List<Thread>();
 
        for (int i = 0; i < 5; i++)
        {
            Thread t = new Thread(new ThreadStart(() =>
            {
                oMyClass.MyMethodWithoutLock();
                oMyClass.MyMethodWithLock();
            }));
            threads.Add(t);
        }
 
        foreach (Thread t in threads)
        {
            t.Start();
        }
 
        Console.WriteLine(DateTime.Now);
    }
}
Now the output is as follows.
Pic2
With Lock

If you can see here, a set of threads has called “MyMethodWithoutLock” method simultaneously. But “MyMethodWithLock” method has been called by only one single thread at a time. After one thread completed executing “MyMethodWithLock” method, then another thread came in and has accessed “MyMethodWithLock”.

Now if you read the above well, it mentioned having created only a single object of “MyClass”. Let’s modify the above code so we are creating several objects of “MyClass” and each thread will be accessing separate objects’ methods.
class Program
{
    static void Main(string[] args)
    {
        List<Thread> threads = new List<Thread>();
 
        for (int i = 0; i < 5; i++)
        {
            Thread t = new Thread(new ThreadStart(() =>
            {
                MyClass oMyClass = new MyClass();
                oMyClass.MyMethodWithoutLock();
                oMyClass.MyMethodWithLock();
            }));
            threads.Add(t);
        }
 
        foreach (Thread t in threads)
        {
            t.Start();
        }
 
        Console.WriteLine(DateTime.Now);
    }
}
The output is as follows.
Pic3
With Lock Different Objects

Now here what has happened is both the methods have been called simultaneously back again. This explains the very basic concept of the lock statement. That is lock will only be blocking some code from accessing multiple threads only when the code belongs to the same object. If the threads are accessing the same method of different objects and you still you want to block some code from multithreaded access, if you use lock statement basically it’s not going to help you.

For more information:
   lock Statement (C# Reference)
   Thread Synchronization

Sample on MSDN Code Gallery:
   Download Sample

Hope this helps. Appreciate your feedback.

Happy Coding.