Saturday, February 18, 2012

Syncronization with lock() - bad habits

Hi all.

Today I wanted to touch the lock statement in C#, and how many developers used to use it. There are a lot of books on C#, where authors bring examples like the following:
public class LibraryType
{
  public void X()
  {
    lock (this)
    {
      // some actions
    }
  }
}
I'd like to touch this because many developers are using the same technique of syncronizing access to a shared resource. There is nothing wrong in such a code, but there is a potential problem hidden in it.
What if somebody, who is going to use the library (which contains above written code) will decide to syncronize access to some shared resource using an instnace of a type, which contains above shown method X()?
In single threaded application there will be no problems at all, but in case of multithreaded applicaiton, the caller will face a deadlock. Take a look to the following code example:
// This code is in different assembly
internal class WrapperClass
{
  private LibraryType libTypeInstance = new LibraryType();

  private void XCaller()
  {
    lock(this.libTypeInstance)
    {
      Thread tmpThread = new Thread(new ThreadStart(()=>this.libTypeInstance.X()));
      tmpThread.Start();
      tmpThread.Join();
    }
  }
}
The thread which is calling the method XCaller() will lock the libTypeInstance object, and then will create another Thread inside, which will try to lock the same object instnace from the inner X() method. So that thread will wait untill the object is not unlocked, but for this to happen that thread should finish its job. So the application will halt here.
So the prefered technique in syncronization scenarios will be to keep a private instancec of an Object type and lock that instance, instead of locking the object (this). This will result in the following change in the code:
public class LibraryType
{
  private Object syncObject = new Object();

  public void X()
  {
    lock (this.syncObject)
    {
      // some actions
    }
  }
}

After the following change the above mentioned example will work with no problems.

Thanks for reading.