3
for (int i = 0; i < 10; i++)
  new Thread (() => Console.Write (i)).Start();

正如预期的那样,上述代码的输出是不确定的,因为 i 变量在循环的整个生命周期中引用相同的内存位置。因此,每个线程都会在一个变量上调用 Console.Write,该变量的值可能会在运行时发生变化

然而,

for (int i = 0; i < 10; i++)
{
  int temp = i;
  new Thread (() => Console.Write (temp)).Start();
}

也给出了非确定性的输出!我认为变量 temp 是每个循环迭代的本地变量。因此,每个线程捕获了不同的内存位置,应该存在 np 问题。

4

4 回答 4

2

您的程序应该有 10 个 lambdas,每个 lambdas 都会将 0 到 9 中的一个数字写入控制台。但是,不能保证线程将按顺序执行。

于 2013-01-25T08:51:18.217 回答
2

也给出了非确定性的输出!

不,这不对。我检查了你的第一个代码(有重复的数字)和第二个(没有)十次。

所以一切正常。正如它应该的那样。

于 2013-01-25T08:51:45.877 回答
1

第二代码片段应该是确定性的,因为每个线程最终都会写入它temp,并且它们的所有时间都会不同。

但是,它不保证线程将按其创建顺序安排执行。您会看到所有可能的温度,但不一定按升序排列。

于 2013-01-25T08:51:40.727 回答
1

这是 OP 正确且他的两段代码都不正确的证明。

并且也有一个有证据的解决方案。

但是需要注意,“非确定性”意味着线程接收到错误的参数订单永远不会得到保证。

下面的代码检查了第二段 OP 代码并证明它按预期工作。

我正在存储这对(线程标识,参数),然后将其打印出来与线程输出进行比较,以证明这些对没有改变。我还添加了几百毫秒的随机睡眠,因此 for 索引在那些时候应该明显改变。

        Dictionary<int, int> hash = new Dictionary<int, int>();
        Random r = new Random(DateTime.Now.Millisecond);
        for (int i = 0; i < 10; i++)
        {
            int temp = i;
            var th = new Thread(() =>
            {
                Thread.Sleep(r.Next(9) * 100);
                Console.WriteLine("{0} {1}", 
                    Thread.CurrentThread.GetHashCode(), temp);
            });

            hash.Add(th.GetHashCode(), temp);

            th.Start();
        }

        Thread.Sleep(1000);
        Console.WriteLine();

        foreach (var kvp in hash)
            Console.WriteLine("{0} {1}", kvp.Key, kvp.Value);
于 2013-01-31T05:48:25.560 回答