Multithreading: Which lock object should i use?

The lock keyword locks a specified code block so two threads can’t process the same code block at the same time. When one threads exits the locked block, another thread can enter the locked code block. The Monitor class offers the same functionality, but you specify the start and end of the locked code block with Monitor.Enter and Monitor.Exit. For both techniques you need a variable to lock on. A common pattern is to lock on this for instance data in a class or typeof(type) for static data.

using System; 
using System.Threading; 

public class LockObject
{
    private static int counter = 0;

    public static void MonitorIncement()
    {
        Monitor.Enter(typeof(LockObject));
        counter++;
        Monitor.Exit(typeof(LockObject));
    }

    public static void LockIncement()
    {
        lock (typeof(LockObject))
        {
            counter++;
        }
    }
}

The problem with this is, this of typeof(type) could also be the lock object in an entirely different synchronization block outside the class in a unrelated code block. The result would be that two completely different synchronization blocks that synchronizes two different sets of data can block each other. The same thing can happen if you use a string a lock variable, because all the strings refer to the same instance. These problems can be solved with a private read-only field to lock on!

public class LockObject
{
    private static int counter = 0;
    private readonly static object syn = new object();

    public static void MonitorIncement()
    {
        Monitor.Enter(syn);
        counter++;
        Monitor.Exit(syn);
    }

    public static void LockIncement()
    {
        lock (syn)
        {
            counter++;
        }
    }
}

The lock object is private so it can’t be used by code blocks outside the class as lock object! The read-only attribute prevents the variable from changes.

One thought on “Multithreading: Which lock object should i use?

  1. While you may be doing this as a simple example, others may quickly oversee that for incrementing,it’s easiest to use the Interlocked class:

    Interlocked.Increment(ref counter);

Comments are closed.