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();
}
private void ThreadFunction()
{
Thread.Sleep( 10000 );
Console.WriteLine( "ThreadFunction Startup Complete trying to call lock(this)" );
while( true )
{
lock(this)
{
Console.WriteLine( "Running Internal ThreadFunction - Starting(takes 3 seconds)" );
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
{
private InternalClass theClass = newInternalClass();
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" );
}
[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.
|