Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multithreading issue updating the value

I have difficulty understanding why the multithreading fails to update values before the thread completes. Does the separate thread have its own copy of the references or values?

If not, to my understanding the code below should work properly when MyMethod is called, but often it does not create instances of some MyType objects in the array before the thread.IsAlive becomes false:

class MyClass
{
    static MyType[] obj = new MyType[Environment.ProcessorCount - 1];
    void MyMethod()
    {
        Thread[] threads = new Thread[Environment.ProcessorCount - 1];

        for (int i = 0; i < Environment.ProcessorCount - 1; i++)
        {
            threads[i] = new Thread(() => FillObjects(i));
            threads[i].Priority = ThreadPriority.AboveNormal;
            threads[i].Start();
        }

        while (threads[i].Any(c => c.IsAlive))
        {
            Thread.Sleep(50);
        }
    }
    void FillObjects(int i)
    {
        obj[i] = new MyType();
        //perform actions with obj[i] to fill it with necessary values
    }
}
like image 384
Almis Avatar asked Sep 16 '15 12:09

Almis


1 Answers

You need to assign the value of the loop variable to a local variable. Otherwise it's possible that the first execution of FillObjects(i) is executed after i was incremented so FillObjects(0) is never called and therefore obj[0] is never assigned.

void MyMethod()
{
    Thread[] threads = new Thread[Environment.ProcessorCount - 1];

    for (int i = 0; i < Environment.ProcessorCount - 1; i++)
    {
        int local = i;
        threads[i] = new Thread(() => FillObjects(local));
        threads[i].Priority = ThreadPriority.AboveNormal;
        threads[i].Start();
    }

    while (threads.Any(c => c.IsAlive))
    {
        Thread.Sleep(50);
    }
}
like image 67
Linky Avatar answered Oct 21 '22 13:10

Linky