Thread-Safe your code with the lock keyword in C#

Dipendra Neupane
codenp
Published in
3 min readDec 1, 2022

--

Photo by Maxwell Nelson on Unsplash

Single-threaded application process one command at a time. It means all the logic or code present in the program will be executed by a single thread only i.e. the Main thread.

Unlike a single-threaded application, a multi-threaded application refers to the concurrent/parallel execution of more than one sequential set (thread) of instructions.

A thread is defined as the execution path of the program. Most of the popular programming languages have the support for implementing multi-threading for increasing the efficiency of an application built.

Multi-threading in C# improves the performance of the processor by executing operations simultaneously. At the same time, Multithreaded processes are quite complicated. This may lead to complications and yield unexpected results if not handled properly.

The code below runs on multiple threads where I want to print two different messages one after another.

using System;
using System.Threading;

namespace ConsoleApp
{
internal class Program
{
private static void Main(string[] args)
{
Thread t1 = new Thread(PrintMessage1)
{
Name = "Thread 1"
};

Thread t2 = new Thread(PrintMessage2)
{
Name = "Thread 2"
};

t1.Start();
t2.Start();

Console.ReadLine();
}

private static void PrintMessage1()
{
Write("I am");
}

private static void PrintMessage2()
{
Write("Thread Safe");
}

private static void Write(string message)
{
for (int x = 0; x < message.Length; x++)
{
Console.Write($"{message[x]}");
Thread.Sleep(TimeSpan.FromSeconds(0.05));
}
Console.Write(" ");
}
}
}

But the output printed out something like this.

c# console window with some message.
Output without lock implementation

The Write method gets executed parallelly on two different threads since this is the shared method. Thread 2 gets executed even before Thread 1 completes its looping on the Write method which is the main point where we are getting an unexpected result.

There are a few different ways to overcome this issue. In this article, we will fix this scenario using the Lock compiler keyword available on C#.

Lock Keyword on C# for Thread-safe code.

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. — learn.microsoft.com “lock statement (C# reference)”

As we saw, when you want multi-thread access to a shared resource, it results in an unexpected outcome. The Thread safe code with the use of the lock keyword looks like below.

using System;
using System.Threading;

namespace ConsoleApp
{
internal class Program
{
static readonly object _lock = new object();
private static void Main(string[] args)
{
Thread t1 = new Thread(PrintMessage1)
{
Name = "Thread 1"
};

Thread t2 = new Thread(PrintMessage2)
{
Name = "Thread 2"
};

t1.Start();
t2.Start();

Console.ReadLine();
}

private static void PrintMessage1()
{
Write("I am");
}

private static void PrintMessage2()
{
Write("Thread Safe");
}

private static void Write(string message)
{
lock (_lock)
{
for (int x = 0; x < message.Length; x++)
{
Console.Write($"{message[x]}");
Thread.Sleep(TimeSpan.FromSeconds(0.05));
}
Console.Write(" ");
}
}
}
}

The outcome on the console looks perfect after the implementation.

c# console window with “I am Thread Safe” message.
Output after lock implementation

Here the dedicated _lock object instance is created and used with the lock keyword around the code block that we want to be accessed by the single thread once at a time.

--

--

Dipendra Neupane
codenp
Editor for

Full-Stack Software Dev | When Dipendra isn't busy crafting code or captivating content, you can find him enjoying a good cup of americano or hitting the Gym.