等待队列与就绪队列

时间:2013-06-06 22:18:05

标签: .net

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

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

2 个答案:

答案 0 :(得分:4)

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

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

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

  1. 请求获取队列中的lock(这会让您进入Monitor的“就绪”队列)。
  2. 获得锁定后,检查队列是否有任何项目。如果没有,您有两种释放锁的选择: a)调用Monitor.Exit,然后调用Monitor.Enter将自己置于“就绪”队列的后面。 b)或者,调用Monitor.Wait,并将自己置于Monitor的“等待”队列中。
  3. 如果你选择选项“a”,那么你的k个线程会浪费CPU周期一遍又一遍地通过就绪队列,找不到任何工作要做,并在队列后面重新开始。

    如果你选择选项“b”,你会说“现在没有什么可以做的,让我睡觉,当有事情要做时叫醒我。”

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

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

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

    有关.NET中生产者/消费者队列的经典实现,请参阅this article

答案 1 :(得分:2)

假设我已正确理解你的问题,两者有不同的用途。

“就绪”队列用于可以在获得锁定后立即运行的线程。他们只是在等待获得锁定。这主要用于互斥,以防止两个线程同时使用相同的资源。

“等待”队列用于等待特定信号的线程 - 即监视器处于脉冲状态。这通常用于协调 - 例如在生产者/消费者队列中,如果队列为空,则消费者将等待监视器在再次检查队列之前发出脉冲。虽然没有人正在生产,没有人消费,但没有线程拥有监视器 - 没有资源在使用。但监视器用于协调消费者与生产者。