繁体   English   中英

使用Monitor.Wait和Monitor.Pulse时发生内存不足异常

[英]Out of memory exception while playing with Monitor.Wait and Monitor.Pulse

我正在使用.NET中的Monitor类,因此我到达了一段似乎正常的代码,但是当我循环一段代码时,它抛出了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次迭代。

对于每对线程,如果线程A设法在线程B之前获取了锁,那么您将最终完成两个线程,并且可以清除所有内容。

如果线程B设法在线程A之前获取了锁,则线程B将完成(对监视器进行了脉动),但是线程A将获取监视器,并永远等待某些东西来触发它。 因此,此时您将拥有:

  • Thread对象
  • 操作系统线程
  • 线程正在等待的对象

...基本上,所有这些都永远捆绑在一起。

鉴于此,对于您遇到问题,我并不感到惊讶。

目前尚不清楚您要实现的目标,但这可以解释症状。 不要假设只是因为你叫threadA.Start()之前threadB.Start()第一个线程实际上第二个线程之前到达代码的某个点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM