C#多线程通过值或参考?

Lea*_*ner 2 c# variables multithreading memory-management pass-by-reference

我在网上看到一段代码,声称调用这样的线程会导致非确定性输出"0223557799"或类似的东西.(你明白了)

for (int i = 0; i < 10; i++)
   new Thread (() => Console.Write (i)).Start();
Run Code Online (Sandbox Code Playgroud)

这就是给出的理由:

"问题是i变量在整个循环的生命周期中引用相同的内存位置.因此,每个线程在一个变量上调用Console.Write,该变量的值可能在运行时发生变化!"

但是,传统上讲,当参数通过值传递时 - 每个新的Thread调用应该发送i增量顺序吗?只有当值通过引用传递时,上述原因才有效.那么,在C#多线程中,值是通过引用传递的吗?

我是C#的新手,请理解这个问题是否天真.

Eri*_*ert 10

您的程序相当于以下程序:

class Locals
{
    public int i;
    public void M() { Console.Write(this.i);
}

...
Locals locals = new Locals();
for (locals.i = 0; locals.i < 10; locals.i++)
  new Thread (locals.M).Start();
Run Code Online (Sandbox Code Playgroud)

现在很清楚为什么你得到了你的结果?它不是i通过价值传递的; 而是通过引用locals传递给每个线程.每个线程都是共享的,因此可以看到当前的值,而不是创建线程时的值. locals.ilocals.ii


Han*_*ant 8

这里有一个以上的问题.它肯定从这个博客文章中描述的for()循环变量捕获问题开始.这往往会产生"10"作为输出,但不能保证会发生这种情况,因为线程可能在循环仍然被迭代时执行.

但是程序也遇到了核心线程问题,并不能保证线程会以预期的顺序调用Console.Write().它只是可能的,但是一个线程可以在另一个线程之前竞争并获得保护控制台的锁定.一个被称为" 穿线竞赛 "的问题.

  • C#5中的更改仅适用于foreach循环,而不适用于循环. (2认同)