等待队列与就绪队列

Yam*_*cha 3 .net

为什么使用监视器时每个对象都有一个就绪和等待队列?如果线程处理完一个对象,只需弹出等待队列中的下一个项目即可。就绪队列似乎是多余的。

上下文是.NET,更具体地说是监视器类。

mbe*_*ish 5

生产者/消费者队列是了解 Monitor 类的一个非常好的用例。

假设工作偶尔添加到队列中。有时有很多项目需要处理,有时会经过很长一段时间而队列中没有项目。

因此,假设您有 k 个消费者线程正在等待处理队列中的项目。换句话说,每个线程都实现一个紧密循环,不断尝试

  1. 请求将其放入lock队列(这会将您置于监视器的“就绪”队列中)。
  2. 获得锁后,检查队列中是否有任何项目。如果没有,您有两种释放锁的选择: a) 调用 Monitor.Exit,然后调用 Monitor.Enter 将自己置于“就绪”队列的后面。b) 或者,调用 Monitor.Wait,并将自己放入 Monitor 的“等待”队列中。

如果您选择选项“a”,您的 k 个线程将浪费 CPU 周期,一遍又一遍地穿过就绪队列,发现没有工作可做,并在队列后面重新开始。

如果你选择选项“b”,你就是在说“现在没什么可做的,让我睡一觉,有事可做的时候叫醒我”。

使用选项“b”,如果队列为空,您很快就会发现所有消费者都在“等待”队列中休眠,并且不会浪费 CPU 时间。

然后,当生产者将项目添加到队列中时,它会调用 Monitor.Pulse。这会唤醒“等待”队列中的第一个线程,然后该线程转到“就绪”队列的末尾(如果“就绪”队列为空,则该线程也是队列的前面)。

当线程获得锁并使用队列中的此项时,它会再次调用 Monitor.Enter,并转到“就绪”队列的后面。

请参阅本文,了解 .NET 中生产者/消费者队列的经典实现。