为什么使用监视器时每个对象都有一个就绪和等待队列?如果一个线程完成了一个对象,只需弹出等待队列中的下一个项目。就绪队列似乎是多余的。
上下文是 .NET,更具体地说是监视器类。
生产者/消费者队列是学习 Monitor 类的一个非常好的用例。
假设工作被偶尔添加到队列中。有时需要处理很多项目,有时会经过很长时间而队列中没有项目。
因此,假设您有 k 个消费者线程等待处理队列中的项目。换句话说,每个线程都实现了一个紧密的循环,不断地尝试
lock
队列(这会将您置于 Monitor 的“就绪”队列中)。如果您选择选项“a”,您的 k 个线程将浪费 CPU 周期,一遍又一遍地在就绪队列中移动,找不到工作要做,并在队列后面重新开始。
如果您选择选项“b”,您的意思是“现在这里无事可做,让我睡觉,有事可做时叫醒我”。
使用选项“b”,如果队列为空,您很快就会发现所有消费者都在“等待”队列中休眠,并且不会浪费 CPU 时间。
然后,当生产者将项目添加到队列中时,它会调用 Monitor.Pulse。这将唤醒“等待”队列中的第一个线程,然后该线程进入“就绪”队列的后面(如果“就绪”队列为空,则该队列也是队列的前面)。
当一个线程获得锁并从队列中消费这个项目时,它会再次调用 Monitor.Enter,并进入“就绪”队列的后面。
有关.NET 中生产者/消费者队列的经典实现,请参阅本文。
假设我已经正确理解了您的问题,则两者的用途不同。
“就绪”队列用于准备好在获得锁后立即运行的线程。他们只是在等待获取锁。这主要用于互斥,以防止两个线程同时使用相同的资源。
“等待”队列用于等待特定信号的线程- 即正在脉冲的监视器。这通常用于协调 - 例如在生产者/消费者队列中,如果队列为空,消费者将等到监视器发出脉冲,然后再次检查队列。虽然没有人在生产,也没有人在消费,但没有线程拥有监视器 - 没有资源在使用。但是监视器用于协调消费者和生产者。