Click here to Skip to main content
15,881,898 members
Articles / Programming Languages / Visual Basic
Article

Managing shared resource access in .NET multi-threading

Rate me:
Please Sign up or sign in to vote.
2.90/5 (7 votes)
14 Mar 20054 min read 60.7K   16  
This document describes the details of a customized .NET ThreadLockHelper class that manages shared resources effectively in .NET multithreading solutions as well as higher level overview of shared resource management and synchronizing techniques in .NETmultithreading.

Introduction

Summary

This document describes the details of a customized .NET ThreadLockHelper class that manages shared resources effectively in .NET multithreading solutions as well as higher level overview of shared resource management and synchronizing techniques in .NET multithreading.

This provides a helper class that simplifies the effort of programmers who are involved in high end programming using multithreading in the Microsoft® .NET Framework. This article also explains how to synchronize access to a shared resource among multiple threads.

This guides you to:

  • Design a better locking mechanism to access shared resources (both managed and unmanaged) using .NET threading model.
  • Make design and implementation decisions to meet complex threading solutions.

This assumes that you are familiar with .NET component development and the basic principles of threading mechanisms.

Contents

  • Shared resource access in multithreading, an overview.
  • Design and implementation of ThreadLockHelper class.
  • Sample applications using ThreadLockHelper class.
  • Conclusion

Shared resource access in multithreading, an overview

A .NET application can perform multiple tasks at the same time by using multithreading. Multithreading permits you to start different threads to complete different tasks at the same time. Multithreading also improves the performance and the responsiveness of applications.

Since multiple threads can access any resource at the same time, it is best to synchronize individual threads with the other parts of the program. When an application is working in a multi threaded environment, it needs to maintain that no thread leaves the object in an invalid state when it gets suspended. Thread safety basically means, the members of an object always maintain a valid state when used concurrently by multiple threads.

.NET provides different synchronization mechanisms that maintain thread safety in multithreading programming.

lock is a keyword that marks a statement block as a critical section by obtaining the mutual-exclusion lock for a given object, executing a statement, and then releasing the lock.

Sample code:

C#
lock(obj) { // code to be locked will go here }

Monitor: The Monitor class is used to synchronize blocks of code, instance methods, and static methods. The locking is performed based on an object, which means that it will not lock properly on value types such as int, string, and so on. When the object is locked, no other thread can utilize the object. The region of code is established by a call to Monitor.Enter() at the start and released by a call to Monitor.Exit().

Sample code:

C#
lock(obj) { // code to be locked will go here }

You can replace the code with Monitor by the following piece of code:

C#
try 
{
    Monitor.Enter(obj);
{ 
    // code to be locked will go here
}
finally
{
    Monitor.Exit(obj);
}

Mutex: When two or more threads within or across processes need to access an operating system resource (basically unmanaged resources), there needs to be a control to limit conflicting access of the resource. The classes derived from WaitHandle must implement a signaling instrument to indicate taking or releasing of exclusive access to a resource. System.Threading.Mutex is a class that is derived from WaitHandle. Only one thread at a time can own a Mutex. Prior to accessing the resource, each thread tries to gain ownership of the Mutex using one of the request signaling methods. If the Mutex is owned, each thread waits for ownership of the resource before continuing. When the thread is done with the Mutex, it signals completion through a call to the ReleaseMutex() method. (lock and Monitor will not be helpful to lock unmanaged resources).

Sample code:

C#
Mutex objMutex = new Mutex(false, "ThreadLock" );
objMutex.WaitOne();
// code to be locked will go here
objMutex.ReleaseMutex();

Design and implementation of ThreadLockHelper class

ThreadLockHelper class is a singleton implementation and only one instance will be taking care of locking threads for a process to be executed. Use the following namespaces to compile the ThreadLockHelper class.

C#
using System;
using System.Threading;
C#
/// <summary>
/// A static class used to lock the managed/unmanaged .net resources
/// </summary>
public class ThreadLockHelper 
{
    static ThreadLockHelper mInstance = null;
    Mutex mMutex = null; 
    
    private ThreadLockHelper ()
    {
    }
    
    public static ThreadLockHelper GetInstance()
    {
      if( mInstance == null )
      {
        mInstance = new ThreadLockHelper (); 
        mInstance.mMutex = new Mutex(false, "ThreadLock" );
      }
      return( mInstance );
    }
    
    
    public bool CreateLock()
    {
      if ( mMutex == null )
      {
        mMutex = new Mutex(false, "ThreadLock"); 
      }
      return( mMutex.WaitOne() );
    }
    
    public void ReleaseLock()
    {
        mMutex.ReleaseMutex();
    } 
}

Sample applications using ThreadLockHelper class

Create a ThreadLockHelper lock before the process is to be executed and release the lock after the process:

C#
public class Activity
{
    public void InvokeTask()
    {
        Task objTask = new Task(); 
        ThreadLockHelper.GetInstance().CreateLock();
        objTask.DoTask();
        ThreadLockHelper.GetInstance().ReleaseLock();
    }
}

Here objTask.DoTask() operation will be accessing a shared resource. (E.g.: Invoking and calling a web service to execute some operation.)

If you are invoking the above InvokeTask() method in different threads as shown below: (Here in a for-loop we are creating and executing 100 threads for the InvokeTask() operation.)

C#
Activity objActivity = null;
Thread thdInvokeTask ;
for(int i=1; i < 100 ; i++)
{
    objActivity = new Activity(); 
    thdInvokeTask = new Thread(new ThreadStart(objClsThread.InvokeTask));
    thdInvokeTask.Start(); 
}

In the above scenario, if you are not applying locking mechanism, your application will fail with thread abort exception.

You can test the scenario by implementing a web service invocation in objTask.DoTask() method.

Conclusion

This article gives you information related to effective management of thread synchronization. It also provides you to go through a custom ThreadLockHelper class that manages shared resources (both managed and unmanaged) effectively for .NET C# applications. Synchronization lock in the application creates overhead when it locks the variable or the object and when it is released. So this can hurt the performance of the application if there are too many locks. Use locks only when they are really required.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
India India
(MCSD) working as an Architect in a leading software organization having more than 8 years core IT experience in Microsoft Technologies.

Comments and Discussions

 
-- There are no messages in this forum --