代码之家  ›  专栏  ›  技术社区  ›  Marc Gravell

Monitor.Wait是否确保字段被重新读取?

  •  22
  • Marc Gravell  · 技术社区  · 16 年前

    lock 将强制重新加载字段中的任何值(基本上起到内存屏障或围栏的作用-我在这方面的术语恐怕有点松散),结果是 曾经 他们自己不需要 volatile .

    (如果我已经错了,就说!)

    一个好的评论是 raised here ,质疑如果代码执行 Wait() Pulse() d、 它是从内存中重新加载字段,还是在寄存器中(等等)。

    或者更简单地说:这个领域需要 不稳定的 等待() ?

    看着反射器, Wait 打电话到 ObjWait ,即 managed internalcall (同 Enter

    bool closing;
    public bool TryDequeue(out T value) {
        lock (queue) { // arbitrary lock-object (a private readonly ref-type)
            while (queue.Count == 0) {
                if (closing) {       // <==== (2) access field here
                    value = default(T);
                    return false;
                }
                Monitor.Wait(queue); // <==== (1) waits here
            }
            ...blah do something with the head of the queue
        }
    }
    

    很明显我能做到 不稳定的 ,或者我可以将其移出,以便退出并重新进入 Monitor 每次都会有脉冲,但我很想知道是不是有 .

    3 回复  |  直到 8 年前
        1
  •  18
  •   Community Mohan Dere    5 年前

    自从 Wait() Monitor 锁定,如果 lock Monitor.Wait() 我也会的。

    希望能回答您的意见:

    的锁定行为 监视器。等待() http://msdn.microsoft.com/en-us/library/aa332339.aspx

    当线程调用Wait时,它会释放对象上的锁 并进入对象的等待队列。对象的就绪队列中的下一个线程(如果有)获取锁并独占使用对象。所有调用 Wait 保持在等待队列中,直到他们接收到脉冲或信号 PulseAll Pulse 发送时,只有等待队列头部的线程受到影响。如果 则等待对象的所有线程都会受到影响。当接收到信号时,一个或多个线程离开等待队列并进入就绪队列。允许就绪队列中的线程重新获取锁。

    .

    如果你问的是关于 班长 意味着记忆障碍 ECMA CLI spec

    12.6.5锁和螺纹:

    System.Threading.Monitor.Enter 或输入同步方法)应隐式执行易失性读取操作,并释放锁( System.Threading.Monitor.Exit 或保留同步方法)应隐式执行易失性写操作。见§12.6.7。

    12.6.7易失性读写:

    volatile read具有“acquire semantics”,意思是保证在CIL指令序列中的read指令之后对内存的任何引用之前进行读取。volatile write具有“release semantics”,这意味着在CIL指令序列中的write指令之前的任何内存引用之后,都保证发生写操作。

    此外,这些博客文章还提供了一些可能感兴趣的细节:

        2
  •  4
  •   Daniel Earwicker    16 年前

    Wait 释放并重新获取锁,但这样做是为了让另一个线程可以取出锁,以便检查共享状态并调用 Pulse 脉搏 我会扔的。如果他们没有 第一根线是 等待 必须

    Monitor 方法是根据本地可检查的规则使用的,然后所有的内存访问都发生在一个锁中,因此只有自动内存屏障支持 lock 相关/必要。

        3
  •  1
  •   Kiril    16 年前

    也许这次我能帮你。。。而不是使用 volatile Interlocked.Exchange 一个整数。

    if (closing==1) {       // <==== (2) access field here
        value = default(T);
        return false;
    }
    
    // somewhere else in your code:
    Interlocked.Exchange(ref closing, 1);
    

    联锁交换 是一种同步机制, 不稳定的 不是。。。我希望这是有价值的(但你可能已经考虑过了)。