Thread Safety

Consider a scenario, I have a static variable in my class. I am spanning multiple thread and my thread method modifying the value of the static variable. You aware that static variables are shared across all instances. Now how do you make sure that one thread changing the shared value is not affecting other threads. Say thread one changes the vlaue of the static variable and set it to 100. Meanwhile some other thread entering into that blok and modifies the value to 200 which will give unexpected result in thread one.



namespace My_Samples
{
using System.Threading;
using System;

public class MyClass
{
static int a = 10;
public void MyMethod()
{
a = a / 2; // or some calculation
Thread.Sleep(100); //You are not sleeping actually, but you are doing some length work here..
Console.WriteLine(Thread.CurrentThread.Name + " - " + a.ToString()); // You are trying to get the value assigned.
}
}

class Program
{
static void Main(string[] args)
{
MyClass obj = new MyClass();
Thread t1 = new Thread(obj.MyMethod);
t1.Name = "Thread 1";
t1.Start();

Thread t2 = new Thread(obj.MyMethod);
t2.Name = "Thread 2";
t2.Start();

Console.WriteLine("Main Method...");
Console.ReadLine();
}
}
}


The output is something looks like

Main Method...
Thread 1 - 2
Thread 2 - 2


Infact, I was expecting the first thread divides a (10) by 2 which is 5, then the 2nd thread divides a (5) by 2 which should be 2. But when the thread 1 was doing its process, the thread 2 enters in to the region and modified the value and thread 1 gets the invalid result.Now lets put the critical region (lock / Monitor) and see whats happening.



public class MyClass
{
static object obj = new object();
static int a = 10;
public void MyMethod()
{
//Lock the locker object. Only one thread can lock the 'obj' at a time.
//Once the lock is obtained, the other thread will wait till the lock is released.
lock (obj)
{
a = a / 2; // or some calculation
Thread.Sleep(100); //You are not sleeping actually, but you are doing some length work here..
Console.WriteLine(Thread.CurrentThread.Name + " - " + a.ToString()); // You are trying to get the value assigned.
}
}
}


The output is something look like (as we desired)

Main Method...
Thread 1 - 5
Thread 2 - 2


Note 1: When you specify the lock keyword, compiler converts it into Monitor.Enter code block, please check SDK on this.

Note 2: The locker/mutex (sometimes it is called mutex variable also, which may not be true, but people call it as mutex variable for easy understanding) variable should be initiated when it is declared. If you move the code that initialize the locker object, then you will again end up with thread safety issue.

No comments:

Post a Comment