Google

C# lock(this) causes deadlocks Home


C# lock(this) causes deadlocks
17/12/2005 posted by Kevin S
Thread safety and syncronisation is an important part of any project, however using the lock keyword in C# can get you into trouble if its used incorrectly by causing inadvertant deadlocks of your code.

What follows is a quick 101 on why you should avoid using lock(this) as a syncronisation technique.

Lets assume we have an Internal class with a Thread and a ThreadFunction Method
class InternalClass
{
	Thread t = null;
	public InternalClass()
	{
		t = new Thread( new ThreadStart( ThreadFunction ) );			
		t.Start();
	}

	/// Internal Thread Function
	private void ThreadFunction()
	{
		// Simulate startup
		Thread.Sleep( 10000 );
		Console.WriteLine( "ThreadFunction Startup Complete trying to call lock(this)" );

		// loop forever
		while( true )
		{
			lock(this)
			{
				Console.WriteLine( "Running Internal ThreadFunction - Starting(takes 3 seconds)" );
				
				// do some work
				Thread.Sleep( 3000 );
				Console.WriteLine( "Running Internal ThreadFunction - Complete" );
			}
		}
	}
}
Notice how lock(this) has been used to protect the thread method, lets assume for a moment that there is something worth protecting there!

In most cases this is fine, the data is protected. The real problem comes if this is a class that is, for example, exposed as an interface only assembly.

This will mean that that the programmer who is using this class has no idea that you have used lock(this) to syncronise your internal data. Image if this programmer, also aware of thread safety locks your class to syncronise his data.
class ClassMain
{
	/// Internal class Object
	private InternalClass theClass = newInternalClass();
	
	/// 
	/// Construction
	/// 
	public ClassMain()
	{
		Console.WriteLine( "Locking Internal Class before Internal ThreadFunction does " );
		lock( theClass )
		{
			Console.WriteLine( "Internal Class Locked - we have inadvertently deadlocked the Internal Class!" );
			
			// do some work
			Thread.Sleep( 30000 );
		}

		Console.WriteLine( "UnLocking Internal Class - Internal Class will now Start Logging" );
	}

	/// 
	/// The main entry point for the application.
	/// 
	[STAThread]
	static void Main(string[] args)
	{
		ClassMain cm = new ClassMain();
						
		Console.WriteLine( "Press Return to exit" );
		Console.ReadLine();
	}
}

By locking the new InternalClass object, they have inadvertently deadlocked your class !!!

	private object  locker = new object();
	
	....
	
	lock( locker )
	{
		....
Moral of the story "Do not use lock(this)" instead create a simple lockable private object and lock this instead.