The unsung hero, Volatile keyword: - c# threading
My mad and blind love with c# threading
When I first saw c# threading code, I just falled in love forever. As days passed by the power and simplicity of “System.Threading” namespace converted my love in to blind love.
Thread t1 = new Thread(SomeThread);
t1.Start(o1);
In case you have not still fallen in love and new to c# threading,
you can start looking at my c#
training threading video from here.
The blind love was but obvious because in today’s modern world parallel task execution is compulsory component.My love helped me to please users with mind blowing UI interfaces, multi-threaded batch processes, until one day…..
End of blind love with c# threads
But one fine day my love with c# thread’s had a bump.I had two threads running and both where updating the same local variable. The updation done by one thread was not visible to the other thread.
Let me detail what I am saying. I had create a local
variable called as “_loop” as shown in the below abstract code snippet. This
variable was set to ‘true’ by default.
class Program
{
bool _loop = true;
…
…
…
}
In the same application I had created one function called as “SomeThread” which will run until the “_loop” is true.
private static void SomeThread(object o1)
{
….
….
while (o._loop)
….
….
while (o._loop)
{}
}
From the main thread I was spawning this some thread which
was running the loop continuously. In this main thread I was setting the
“_loop” to false. In other words the infinite loop of “SomeThread” should stop
and exit…VOILA it did not.
static void Main(string[] args)
{
Thread t1 = new Thread(SomeThread);
t1.Start(o1);
o1._loop = false;
….
….
….
….
}
Below is the complete source code, you download and see it
for yourself. https://skydrive.live.com/redir?resid=658DB05866C4E8A3!257&authkey=!ABOTw_YQ_czfnNc
bool _loop = true;
static void Main(string[] args)
{
Program o1 =
new Program();
Thread t1 =
new Thread(SomeThread);
t1.Start(o1);
Thread.Sleep(2000);
o1._loop =
false;
Console.WriteLine("Value Set to false");
}
private static
void SomeThread(object o1)
{
Program o =
(Program)o1;
Console.WriteLine("Loop Starting...");
while
(o._loop)
{}
Console.WriteLine("Loop
Stopping...");
}
If you run the above code you can see the infinite loop starting,
but I does not end even if the value was set to “false”.
You can also see the actual video demo of the code by clicking on c# training for threading .
Note :- When you run the code ensure that you have selected
release with CNTRL + F5 pressed.
Why did my love ditch me:- Local Thread memory storage and synchronization
After so many years of successful relationship it was
difficult to believe this unexpected behavior. So I started googling to get
reasons for it.
After long hours of reading, I was stunned that there are two kinds of memory we have to deal when it comes to threading.
One is the main memory where our variables are allocated and the thread also has his own local memory…SURPRISED, same here.
In other words the “_loop” is present at three places one in the main memory and second in the local memories of “mainthread” and “somethread” functions.
When the program kick starts the “_loop” is set to true. So all the memory storages have “_loop” set to true. See the below visual representation.
As the program runs the main thread set the value to false.
This updation is done in the local memory of “mainthread” and main the memory,
but it does not update the local memory of “SomeThread”. So the “SomeThread” function
still sees the stale value and keeps running in a loop.
Below is a visual
representation of how things look internally at various points.
The unsung hero: - Volatile keyword
All relationships have problem, we just need to adjust, find solution and move with life. I was definitely in no mood of leaving c# threading after such a wonderful relationship.
The solution to get around this multiple memory storages was “VOLATILE” keyword.
If you declare your variable as volatile the thread tries to access values from main memory rather than from his local memory where data is stale. It does slow down a bit but it addresses this big confusion.
See it yourself, take the same source code and change the
“_loop” variable to volatile as shown in the below code snippet and run it.
class Program
{
volatile bool _loop =
true;
Ensure that you select mode “release” and hit control + f5 to see the expected behavior.
Feel and See it yourself
In case you want to see it live what I have said in this blog see the video below
http://www.youtube.com/watch?v=DZUXDSEuqek
http://www.youtube.com/watch?v=DZUXDSEuqek
You can also see it yourself by downloading the code from
the below link.