Thread alters passed Int, if start() is called separately

前端 未结 1 968
没有蜡笔的小新
没有蜡笔的小新 2021-01-27 21:52

I\'ve read some things on threading and know that I should lock up a variable that is being accessed by multiple threads. The problem that I am experiencing is that the value i

1条回答
  •  伪装坚强ぢ
    2021-01-27 22:48

    Your problem is in the use of lambda expressions here where you are forming a closure over the loop variable x, not its value at that point. As a result, when the threads actually start, the value of x may have changed (because the loop has executed further iterations) and it is the new value that is passed to your methods.

    If you are using ReSharper, it will warn you of an "Access to modified closure".

    Note that your "working" version is still vulnerable the problem, but as the threads are started in the loop, there's a greater chance that the value of x won't have changed (especially with your 50ms sleep in there). However if one of the threads takes > 50ms to start up, you will still see the wrong value.

    You can fix this by copying the value of x to a local variable inside the loop. This will fix the code in both cases - whether you start the threads in this loop, or store the threads into the MainThreads/WorkingThreads arrays and start them later. Your 50ms sleep should also no longer be required.

        for (Int32 x = 0; x < WorkingQueueList.Count; x++)
        {
            var localX = x;
            Console.WriteLine("Starting x: " + x);
            /* MainThreads[x] = */ new Thread(() => MainQueueToWorkingQueue(localX)).Start();
            /* WorkingThreads[x]  =*/ new Thread(() => WorkingQueueToJob(localX)).Start();
        }
    

    You can read more about this issue here: http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx

    0 讨论(0)
提交回复
热议问题