1

.NET で Monitor クラスを操作していたので、動作しているように見えるコードにたどり着きましたが、しばらくループすると .NET がスローされOutOfMemoryExceptionます。

これを 8 GB の RAM を搭載した 64 ビット Windows 8 開発者用マシンで実行していますが、プロセスが RAM で 100 MB を超えるスペースを占有することはありません。

これは私のコードです:

    using System;
    using System.Threading;

    public class Program
    {
        public static void Main()
        {
            while (true) {

                object theLock = new Object();
                Thread threadA = new Thread(() =>
                {
                    Console.WriteLine("Thread A before lock");
                    lock (theLock)
                    {
                        Console.WriteLine("Thread A locking, about to Wait");
                        Monitor.Wait(theLock);
                    }
                    Console.WriteLine("Thread A after lock");
                });

                Thread threadB = new Thread(() =>
                {
                    Console.WriteLine("Thread B before lock");
                    lock (theLock)
                    {
                        Console.WriteLine("Thread B lockint, about to Pulse");
                        Monitor.Pulse(theLock);
                    }
                    Console.WriteLine("Thread B before lock");
                });

                threadA.Start();
                threadB.Start();

                GC.Collect();

            }
        }
    }

ここで、断片化の問題である可能性があることを読みGC.Collect()、最後に を追加しました。ただし、大きなスペースを割り当てているわけではありません。

次に、ループが例外をスローする前にループが何回繰り返されるかを測定し、カウンターを追加することにしました。

    using System;
    using System.Threading;

    public class Program
    {
        public static void Main()
        {
            int counter = 0;

            while (true) {
                Console.WriteLine(counter);
                counter++;

                object theLock = new Object();
                Thread threadA = new Thread(() =>
                {
                    Console.WriteLine("Thread A before lock");
                    lock (theLock)
                    {
                        Console.WriteLine("Thread A locking, about to Wait");
                        Monitor.Wait(theLock);
                    }
                    Console.WriteLine("Thread A after lock");
                });

                Thread threadB = new Thread(() =>
                {
                    Console.WriteLine("Thread B before lock");
                    lock (theLock)
                    {
                        Console.WriteLine("Thread B lockint, about to Pulse");
                        Monitor.Pulse(theLock);
                    }
                    Console.WriteLine("Thread B before lock");
                });

                threadA.Start();
                threadB.Start();

                GC.Collect();

            }
        }
    }

これにより、例外のスローが大幅に遅くなるようです。36000回の繰り返しを測定しました。

4

1 に答える 1

4

スレッドのペアごとに、スレッド A がスレッド B の前にロックを取得できた場合、両方のスレッドが完了することになり、すべてをクリーンアップできます。

スレッド B がスレッド A の前にロックを取得できた場合、スレッド B は (モニターにパルスを送信して) 完了しますが、スレッド A はモニターを取得し、何かがパルスを送信するのを永遠に待ちます。したがって、その時点で次のようになります。

  • Threadオブジェクト_
  • OS スレッド
  • スレッドが待機しているオブジェクト

...基本的に、それらはすべて永遠に縛られています。

それを考えると、あなたが問題を見ていることに私は驚かない。

何を達成しようとしているのかは明確ではありませんが、それは症状を説明しています。threadA.Start()beforeを呼び出したからthreadB.Start()といって、最初のスレッドが 2 番目のスレッドより前にコード内の特定のポイントに実際に到達するとは決して考えないでください。

于 2015-04-09T14:47:03.683 に答える