I am trying to fully understand how creating separate threads that call the same method of a class instance can effect local variables in the method.
For example I have a class with a single method (Divide)
public class Maths
{
public int Num1;
public int Num2;
public void Divide()
{
for (long i = 0; i < 100000; i++)
{
Num1 = 2;
Num2 = 2;
int result = Num1 / Num2;
Num1 = 0;
Num2 = 0;
}
}
}
Two threads are instantiated and the divide method called as follows:
static void Main(string[] args)
{
Maths m = new Maths();
Task t1 = new Task(() => m.Divide());
Task t2 = new Task(() => m.Divide());
List<Task> tl = new List<Task> { t1, t2 };
Parallel.ForEach(tl, task => task.Start());
Console.ReadLine();
}
}
Sometimes this code runs ok. But other times it throws a dividebyzero error on the line:
int result = Num1 / Num2;
My assumption is that one of the threads is resetting the Num1 and Num2 to zero just before the other thread calls the Num1 / Num2. Therefore causing a divide by zero exception.
This would make sense and I should use a lock but I don't understand how these local variables Num1 and Num2 are shared between the threads because my understanding was that local variables are not shared between threads?
You are right that local variables are not shared between threads (typically, each time method is called, new set of it's local variables is allocated on the stack of executing thread, so local variables of each method call are completely separate and modification of one of them have no effect on the others).
But unfortunatelly Num1
and Num2
are not local variables, but fields. Fields of the same instance of a class are shared between threads.
You would need to declate them like this to make them local variables:
public class Maths
{
public void Divide()
{
int Num1;
int Num2;
for (long i = 0; i < 100000; i++)
{
Num1 = 2;
Num2 = 2;
int result = Num1 / Num2;
Num1 = 0;
Num2 = 0;
}
}
}
Alternatively, you coud create separate instance of Maths
class for each thread, so each thread would use fields Num1
and Num2
of different instances of Maths
class:
static void Main(string[] args)
{
Maths m1 = new Maths();
Maths m2 = new Maths();
Task t1 = new Task(() => m1.Divide());
Task t2 = new Task(() => m2.Divide());
List<Task> tl = new List<Task> { t1, t2 };
Parallel.ForEach(tl, task => task.Start());
Console.ReadLine();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With