为什么Monitor类保留2个队列:和“等待"? [英] Why does Monitor class keep 2 queues: "ready" and "waiting"?

查看:248
本文介绍了为什么Monitor类保留2个队列:和“等待"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据 MSDN :

Monitor类包含静态(在C#中)或Shared(在Visual中) 基本)方法,该方法在控制对对象的访问权限的对象上进行操作 关键部分.为每个维护以下信息 同步对象:

The Monitor class consists of static (in C#) or Shared (in Visual Basic) methods that operate on an object that controls access to the critical section. The following information is maintained for each synchronized object:

  • 对当前持有锁的线程的引用.

  • A reference to the thread that currently holds the lock.

ready 队列的引用,其中包含准备好获取锁的线程.

A reference to a ready queue, which contains the threads that are ready to obtain the lock.

waiting 队列的引用,该队列包含等待锁定状态更改通知的线程 对象.

A reference to a waiting queue, which contains the threads that are waiting for notification of a change in the state of the locked object.

在此线程中,这两个队列引起了一些细微的问题.

And in this thread, the 2 queues are causing some subtle issue.

我认为上述线程中问题的根本原因是有2个队列.如果只有 ONE 队列,则每当Monitor.Pulse()时,只能调度该单个队列中的一个线程. 多个线程无法同时处于就绪状态.因此,该问题永远不会发生.

I think the root cause of the issue in above thread is there are 2 queues. If there's only ONE queue, whenever the Monitor.Pulse(), only one thread from that single queue can be scheduled to run. There's no way for more than one threads to be in ready state at the same time. So the issue should never happen.

那么Monitor为什么要保留2个队列?

So why does a Monitor keep 2 queues?

推荐答案

我认为您误解了该帖子.问题不是由Monitor引起的,而是由 OP的Queue类中的真正逻辑错误引起的.

I think you misunderstood that SO post. The problem was not caused by Monitor but by a genuine logic error in that OP's Queue class.

Remove是一个熟悉的模式,它应使用while而不是if:

The Remove is a familiar pattern, it should use a while instead of an if:

lock (q)
{
    // if (q.Count == 0)
    while (q.Count == 0)
    {
        Monitor.Wait(q);
    }
    ... // use it, we are now sure that q.Count > 0
}

然后您可能需要其他方法(CancellationToken)来结束整个过程.

And then you may want an additional way (CancellationToken) to end the whole process.

一个Monitor可以有2种等待线程,实现者选择使用2个队列.使用1个队列似乎是可能的,但这不会改变任何事情.它仍然仍然只能在任何时间运行1个线程,因此您的理解在这一点上是不对的.

A Monitor can have 2 sorts of waiting threads, the implementers chose to use 2 queues. Using 1 queue seems possible but that wouldn't change a thing. It would still allow only 1 thread to run at any time, so your understanding goes wrong at this point somehow.

正在发生的事情是,排队的线程可以具有以下两种状态之一:

What is happening is that a queued thread can have one of two states:

  • 当线程调用lock(q)并且已获取锁定时,该线程以 Ready
  • 排队.
  • 当线程调用Wait(q)时,它被排队为正在等待,并且需要Pulse()唤醒
  • 当调用Pulse()时,1个等待线程移至就绪"状态.但是它不会立即运行,它必须等待轮到它.根据定义,仅当获得锁定时才能调用Pulse().
  • 当重新激活Pulsed线程时,情况可能已经改变(即,另一个线程消耗了数据元素).
  • when a thread calls lock(q) and the lock is already taken, it is queued as Ready
  • when a thread calls Wait(q) it is queued as Waiting and needs a Pulse() to wake
  • When Pulse() is called, 1 Waiting thread is moved to the Ready state. But it will not immediately run, it will have to wait its turn. By definition, Pulse() can only be called when the lock is taken.
  • When the Pulsed thread is reactivated, the situation may have changed (ie, another thread consumed the data element).

当没有线程正在等待脉冲时,脉冲/等待机制是不可靠的.通常,您不能完全依赖Pulse/Wait进行簿记. 并且Monitor的合同不包括 公平

The Pulse/Wait mechanism is sort of unreliable, when no thread is Waiting a Pulse goes unnoticed. You can't in general rely on Pulse/Wait for exact bookkeeping. And the contract of Monitor does not include fairness

这篇关于为什么Monitor类保留2个队列:和“等待"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆