What is Thread Synchronization?
There s a couple of context you want to consider when defining Thread Synchronization.It is a mechanism where in the critical section (code block or resource) is accessible to only one thread at a time.
It a mechanism where one thread waits for other thread to finish executing before continuing with the execution .
failing to handle these will result in race conditions ,unpredictable results and dead locks.
lets go over the options available in c# to when working with thread synchronization .
If you want to limit the number of thread that can access a resource or block of code at a time ,then
your options are lock, Monitor,Mutex,SpinLock,Semaphore .
If you want to pause a thread's execution till you get a notification from other thread then your options are AutoResetEvent,ManulResetEvent,CountDownEvent,Barrier, Wait and pulse .
In the first part of this post we will look at locking options C#.
Lock
It provides a very basic exclusive lock for a code block letting one thread access the code block
below is a trivial example for the same ..
now the below code is thread safe with lock .
below is a trivial example for the same ..
public class ThreadNotSafe
{ int _v1 = 1;
int _v2 = 1;
public void Execute()
{
if (_v2 != 0)
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine("Result is " + _v1 / _v2);
}
_v2 = 0;
}
else
{
Console.WriteLine("Invalid Operation");
}
}
}
static void Main(string[] args)
{
ThreadNotSafe unsafeObject = new ThreadNotSafe();
Thread thread1 = new Thread(unsafeObject.Execute);
Thread thread2 = new Thread(unsafeObject.Execute);
thread1.Start();
thread2.Start();
Console.ReadLine();
}
The above Execute function seems safe as we are checking if _v2 is zero only then we proceed with the division , but when this method is accessed by two different threads more often then not you will end up with the divide by zero error.now the below code is thread safe with lock .
public void Execute()
{
lock (this)
{
if (_v2 != 0)
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine("Result is " + _v1 / _v2);
}
_v2 = 0;
}
else
{
Console.WriteLine("Invalid Operation");
}
}
}
Monitor
The lock syntax discussed above is a shortcut for Monitor.Enter and Monitor.Exit, The Monitor object offer more flexibility than lock like Monitor.TryEnter which can return a bool value if the lock is already taken and you can also specify a timeout value if you want to wait for sometime before trying to enter the code block.
below is the sample for same where in the second thread try's to enter the critical section after waiting for two seconds .
public void Execute()
{
if (Monitor.TryEnter(this,2000))
{
try
{
if (_v2 != 0)
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine("Result is " + _v1 / _v2);
}
_v2 = 0;
}
else
{
Console.WriteLine("Invalid Operation");
}
}
catch (Exception)
{
throw;
}
finally
{
Monitor.Exit(this);
}
}
}
** More to explore on Monitor Object is Monitor.Pluse ,PluseAll ,Overloads of Monitor.TryEnter,Mintor.Enter.
What is Deadlock?
Is a situation where in one thread waits for a resource to be release held by the other thread, below is a trival example where is deadlock situation occurs .
public class Deadlock
{
private static readonly object _lock1 = new object();
private static readonly object _lock2 = new object();
public void Deadlock1()
{
lock (_lock1)
{
Console.WriteLine("i m in Deadlock1 with lock on _lock1");
//simulate loong running proceess
for (int i = 0; i < 10000; i++)
{
}
Console.WriteLine("i m in Deadlock1 with lock on _lock1 i need access to _lock2");
lock (_lock2)
{
Console.WriteLine("i got _lock2");
}
}
}
public void Deadlock2()
{
lock (_lock2)
{
Console.WriteLine("i m in Deadlock2 with lock on _lock2");
//simulate loong running proceess
for (int i = 0; i < 10000; i++)
{
}
Console.WriteLine("i m in Deadlock2 with lock on _lock2 i need acces to _lock1");
lock (_lock1)
{
Console.WriteLine("i got _lock1");
}
}
}
}
static void Main(string[] args)
{
Deadlock _deadLock = new Deadlock();
Thread thread1 = new Thread(_deadLock.Deadlock1);
Thread thread2 = new Thread(_deadLock.Deadlock2);
thread1.Start();
thread2.Start();
}
Mutex
Mutex works exactly like lock does but the major difference is that it works across process , you will want to consider mutex for thread synchronization option when working with multiple instance of the application.
If you have a multiple instance of your application running and if your application writes to a file , then ideally you would want to write to file from one application at a time .Mutex is ideal for this kind of scenario .
class MutexTest
{
public static void SimulateFileWrite()
{
Mutex mutex = new Mutex(true, "http://sanathwindowsdev.blogspot.in/");
if (!mutex.WaitOne(3000))
{
Console.WriteLine("Other instance has the lock");
}
else if (mutex.WaitOne())
{
Console.WriteLine("simulating writing to a file");
Thread.Sleep(10000);
mutex.ReleaseMutex();
Console.WriteLine("simulating writing to a file done");
Console.ReadKey();
}
}
static void Main(string[] args)
{
SimulateFileWrite();
}
}
build the above code and run the exe twice,you can notice that only one app simulates the write to file at a time.
Semaphore
Semaphore is similar to mutex , but the Semaphore is not an exclusive lock , it controls the number of thread that is allowed to enter the critical section of the code .
class SemaphoreTest
{
static Semaphore semaphore = new Semaphore(3,3);
public static void CriticalSection(object threadID)
{
Console.WriteLine(threadID + "is Entering");
semaphore.WaitOne();
Console.WriteLine(threadID + " Entered");
Thread.Sleep(2000 * (int)threadID);
Console.WriteLine(threadID + " Leaving");
semaphore.Release();
}
static void Main(string[] args)
{
for (int i = 1; i < 6; i++)
{
new Thread(CriticalSection).Start(i);
}
Thread.Sleep(20000);
Console.ReadKey();
}
}
When you run the above code all the time you can see that only three threads has access to critical section of the code.
We discussed about thread synchronization by locking , in the next article we will discuss about thread synchronization using signaling.
We discussed about thread synchronization by locking , in the next article we will discuss about thread synchronization using signaling.

0 comments:
Post a Comment