C#线程内存异常

时间:2010-12-07 16:28:30

标签: c# multithreading out-of-memory

我正在做一些大学工作,我应该模拟10,100,1,000和10,000个线程执行1,000,000次锁定并以互斥锁(static Mutex m_mutex = new Mutex();)和信号量解锁为互斥锁({{1 ,对吗?)。

我在前三种情况下没有遇到任何问题,但我在10,000个线程中遇到了内存异常。我的代码:

static SemaphoreSlim m_semaphore = new SemaphoreSlim(1);

我应该进行10次测试并测量平均值。

        resultados.WriteLine("=== 10 threads ===");
        ts = new TimeSpan();
        media = 0;
        parcial = 0;
        resultados.WriteLine("Parciais:");
        for (int i = 0; i < 10; i++)
        {
            parcial = LockAndUnlock_Semaphore_ComDisputa(10);
            media += parcial;
            ts = TimeSpan.FromTicks(parcial);
            resultados.WriteLine(ts.ToString());
        }
        ts = TimeSpan.FromTicks(media / 10);
        resultados.WriteLine("Média: " + ts.ToString());

当我发布这个问题时,我正在尝试,但是这个我创建了这样的线程向量:

private static long LockAndUnlock_Semaphore_ComDisputa(int numeroDeThreads)
    {
        Thread[] threads10 = new Thread[10];
        Thread[] threads100 = new Thread[100];
        Thread[] threads1000 = new Thread[1000];
        Thread[] threads10000 = new Thread[10000];
//switch in the numeroDeThreads var
//[...]
 case 10000:
 sw.Start();
 for (int i = 0; i < numeroDeThreads; i++)
 {
      threads10000[i] = new Thread(LockUnlockSemaphore);
      threads10000[i].Priority = ThreadPriority.Highest;
      threads10000[i].Start();
 }
 for (int i = 0; i < numeroDeThreads; i++)
 {
      threads10000[i].Join();
 }
 sw.Stop();
 break;
//[...]
return sw.ElapsedTicks;


 static void LockUnlockSemaphore()
    {
        for (int i = 0; i < 1000000; i++)
        {
            m_semaphore.Wait();
            //thread dentro do semaforo
            m_semaphore.Release();
        }
    }

我应该在互斥锁和信号量中测试互斥锁,但错误发生在正确的互斥锁中。

修改

即使使用Thread [] threads = new Thread [numeroDeThreads];我得到了outofmemoryexception =(...

提前致谢,

Pedro Dusso

3 个答案:

答案 0 :(得分:6)

10000个线程将导致大量分配的堆栈空间,每个线程默认为1兆字节。 CLR将提交此内存,要求它可用,要求您的进程能够使用10000 MB的内存。 32位应用程序无法具有超过2 GB的映射进程内存,从而导致此行为。

请参阅可能为您提供更多信息的博客条目Managed threads in "whole stack committed" shocker

答案 1 :(得分:1)

由于这只是测试,您可能希望将Joe Duffy explains的默认堆栈大小降低到更合理的水平。执行此操作的两种方法是使用线程构造函数来限制大小,或者可以使用Editbin。

下面将它从1MB减少到256KB,这将使你在内存不足之前可以创建的线程数量大约翻两番。

EDITBIN.EXE FOO.EXE /STACK:262144

editbin的优势在于它适用于包括池化线程在内的所有线程。

注意如果您使用VS命令提示符,这将正常工作。如果使用普通命令提示符,则需要手动解析dll链接

答案 2 :(得分:0)

在Windows中,默认堆栈大小为1MB。

1MB * 10.000个线程=仅10GB的堆栈大小。

也许,你应该重新考虑你的架构。