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 個のラムダが必要で、それぞれが 0 から 9 までの数字の 1 つをコンソールに書き込みます。ただし、スレッドが順番に実行されるという保証はありません。

于 2013-01-25T08:51:18.217 に答える
2

また、非決定論的な出力を提供しています!

いいえ、ちがいます。私はあなたの最初のコード (繰り返し番号を持っていた) と 2 番目のコード (繰り返していなかった) を 10 回チェックしました。

したがって、すべて正常に動作します。当然のことです。

于 2013-01-25T08:51:45.877 に答える
1

これは、OP が正しく、彼のコードの両方の部分が正しくないという証拠です。

また、証明付きの解決策もあります。

ただし、「非決定論的」とは、スレッドが間違ったパラメーターを受け取ることを意味することに注意する必要があります。注文は保証されません。

以下のコードは、OP コードの 2 番目の部分を調べて、期待どおりに動作していることを示しています。

ペア (スレッド ID、パラメーター) を保存し、それを印刷してスレッド出力と比較し、ペアが変更されていないことを証明します。また、数百ミリ秒のランダム スリープを追加したので、その時点で 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 に答える
1

2 番目のコードスニペットは、各スレッドが最終的にそのtemp.

ただし、スレッドが作成された順序で実行されるようにスケジュールされることは保証されません。考えられるすべての一時が表示されますが、必ずしも昇順であるとは限りません。

于 2013-01-25T08:51:40.727 に答える