0

I have a program that starts 2 threads and use Join.My understanding says that joins blocks the calling operation till it is finished executing .So,the below program should give 2 Million as answer since both the threads blocks till execution is completed but I am always getting the different value.This might be because first thread is completed but second thread is not run completely. Can someone please explain the output.

Reference -Multithreading: When would I use a Join?

namespace ThreadSample
{
    class Program
    {
        static int Total = 0;
        public static void Main()
        {
            Thread thread1 = new Thread(Program.AddOneMillion);
            Thread thread2 = new Thread(Program.AddOneMillion);

            thread1.Start();
            thread2.Start();

            thread1.Join();
            thread2.Join();

            Console.WriteLine("Total = " + Total);
            Console.ReadLine();
        }
        public static void AddOneMillion()
        {
            for (int i = 1; i <= 1000000; i++)
            {
                Total++;
            }
        }
    }
}
Vicky
  • 41
  • 5
  • 1
    Have you tried using [`Interlocked.Increment`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.interlocked.increment?view=netcore-3.1)? – Emanuel Vintilă Jun 01 '20 at 15:29
  • yes and that works fine.My doubt is what is the flow of execution of above program.Why 2 Million is not the answer when both thread uses Join to halt the execution of calling thread, – Vicky Jun 01 '20 at 15:31

2 Answers2

1

It's because the increment operation is not done atomically. That means that each thread may hold a copy of Total and increment it. To avoid that you can use a lock or Interlock.Increment that is specific to incrementing a variable.

Clarification:

thread 1: read copy of Total
thread 2: read copy of Total
thread 1: increment and store Total
thread 2: increment and store Total (overwriting previous value)

I leave you with all possible scenarios where things could go wrong.

I would suggest avoiding explicit threading when possible and use map reduce operations that are less error prone.

You need to read about multi-threading programming and functional programming constructs available in mainstream languages. Most languages have added libraries to leverage the multicore capabilities of modern CPUs.

Tarik
  • 10,810
  • 2
  • 26
  • 40
  • Thanks but if each thread is holding copies,the main thread should wait till both thread1 and thread2 are completed as we have Join used .Then it should display result. Kindly pardon my understanding – Vicky Jun 01 '20 at 15:38
1

When you call start method of thread, it starts immediately. hence by the time u call join on the thread1, thread2 would also have started. As a result variable 'Total' will be accessed by both threads simultaneously. Hence you will not get correct result as one thread operation is overwriting the value of 'Total' value causing data lose.

    public static void Main()
    {
        Thread thread1 = new Thread(Program.AddOneMillion);
        Thread thread2 = new Thread(Program.AddOneMillion);

        thread1.Start(); //starts immediately
        thread2.Start();//starts immediately

        thread1.Join(); //By the time this line executes, both threads have accessed the Total varaible causing data loss or corruption.
        thread2.Join();

        Console.WriteLine("Total = " + Total);
        Console.ReadLine();
    }

Inorder to correct results either u can lock the Total variable as follows

    static object _l = new object();

    public static void AddOneMillion()
    {
        for (int i = 0; i < 1000000; i++)
        {
            lock(_l)
                ii++;
        }
    }

U can use Interlocked.Increment which atomically updates the variable. Please refer the link posted by @Emanuel Vintilă in the comment for more insight.

    public static void AddOneMillion()
    {
        for (int i = 0; i < 1000000; i++)
        {
            Interlocked.Increment(ref Total);
        }
    }
neelesh bodgal
  • 632
  • 5
  • 14