我正在研究 .NET 中的 Monitor 类,所以我找到了一段似乎可以正常工作的代码,但是当我将它循环一段时间时,它会抛出 OutOfMemoryException
.
我在具有 8 GB RAM 的 64 位 Windows 8 开发人员计算机上运行此程序,并且我的进程从未占用超过 100 MB 的 RAM 空间。
Đây là mã của tôi:
using System;
using System.Threading;
chương trình lớp học công cộng
{
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();
}
}
}
我读了đây这可能是一个碎片问题,我在最后添加了 GC.Collect()
。但是我没有分配大块空间。
然后我决定测量循环在抛出异常之前大约经历了多少次迭代并添加了一个计数器:
using System;
using System.Threading;
chương trình lớp học công cộng
{
public static void Main()
{
bộ đếm int = 0;
while (true) {
Console.WriteLine(counter);
bộ đếm++;
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 将获取监视器并mãi mãi等待某个东西向它发出脉冲。所以到那时你将拥有:
- một
线程
对象
- 一个操作系统线程
- 线程正在等待的对象
...基本上,所有这些都永远捆绑在一起。
鉴于此,我对您遇到问题并不感到惊讶。
不清楚您要达到的目标,但这可以解释症状。永远不要假设仅仅因为您在 threadB.Start()
Đã gọi trước threadA.Start()
,第一个线程实际上会在第二个线程之前到达代码中的特定点。
Tôi là một lập trình viên xuất sắc, rất giỏi!