难道Monitor.Wait确保字段是重读? [英] Does Monitor.Wait ensure that fields are re-read?

查看:168
本文介绍了难道Monitor.Wait确保字段是重读?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

人们普遍接受的(我相信!),一个锁定将迫使任何值从字段重新加载(基本上充当内存屏障或栅栏 - 我的术语在这方面变得有点松,我怕),其结果是只有那些领域的永远的一个锁定里面的访问,不应该自己必须挥发性

It is generally accepted (I believe!) that a lock will force any values from fields to be reloaded (essentially acting as a memory-barrier or fence - my terminology in this area gets a bit loose, I'm afraid), with the consequence that fields that are only ever accessed inside a lock do not themselves need to be volatile.

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

(If I'm wrong already, just say!)

有一个很好的评价是<一个href="http://stackoverflow.com/questions/2430609/c-is-it-possible-to-interrupt-a-specific-thread-inside-a-threadpool/2430684#2430684">raised这里,质疑是否也是同样的道理,如果code做了等待() - 即一旦它已脉冲() D,它会重新从内存领域,或者他们能在一个寄存器(​​等)。

A good comment was raised here, questioning whether the same is true if code does a Wait() - i.e. once it has been Pulse()d, will it reload fields from memory, or could they be in a register (etc).

或者更简单地说:的确领域需挥发性,以确保获得电流值后恢复时,等待()

Or more simply: does the field need to be volatile to ensure that the current value is obtained when resuming after a Wait()?

看着反射器,等待要求分解成 ObjWait ,这是管理​​internalcall (同​​输入)。

Looking at reflector, Wait calls down into ObjWait, which is managed internalcall (the same as 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
    }
}

很显然,我可以只让挥发性,或者我可以移动了这一点,让我退出并重新进入显示器每次得到脉冲的时间,但我很好奇知道是否是任意的需要

Obviously I could just make it volatile, or I could move this out so that I exit and re-enter the Monitor every time it gets pulsed, but I'm intrigued to know if either is necessary.

推荐答案

由于等待()方法释放并重新获取了显示器锁,如果锁定执行存储栅栏语义,那么 Monitor.Wait()的意志为好

Since the Wait() method is releasing and reacquiring the Monitor lock, if lock performs the memory fence semantics, then Monitor.Wait() will as well.

要希望解决您的评论:

Monitor.Wait()的锁定行为是在文档(<一href="http://msdn.microsoft.com/en-us/library/aa332339.aspx">http://msdn.microsoft.com/en-us/library/aa332339.aspx),强调说:

The locking behavior of Monitor.Wait() is in the docs (http://msdn.microsoft.com/en-us/library/aa332339.aspx), emphasis added:

当一个线程调用wait,它释放的对象上的锁,进入对象的等待队列。在对象的就绪队列中的下一个线程(如果有)获得锁和独占使用该对象。调用所有线程等待留在排队等候,直到他们从脉冲接收信号或 PulseAll ,由业主发出的锁。如果脉冲发送,只在等待队列头部的线程会受到影响。如果 PulseAll 发送,正在等待该对象的所有线程都受到影响。当接收到信号时,一个或多个线程离开等待队列和进入就绪队列。在就绪队列中的线程被允许重新获取锁。

When a thread calls Wait, it releases the lock on the object and enters the object's waiting queue. The next thread in the object's ready queue (if there is one) acquires the lock and has exclusive use of the object. All threads that call Wait remain in the waiting queue until they receive a signal from Pulse or PulseAll, sent by the owner of the lock. If Pulse is sent, only the thread at the head of the waiting queue is affected. If PulseAll is sent, all threads that are waiting for the object are affected. When the signal is received, one or more threads leave the waiting queue and enter the ready queue. A thread in the ready queue is permitted to reacquire the lock.

这时候调用线程重新获取锁的对象方法返回

如果你问有关的基准是否锁定 /后天显示器意味着内存屏障, ECMA CLI规范说以下内容:

If you're asking about a reference for whether a lock/acquired Monitor implies a memory barrier, the ECMA CLI spec says the following:

12.6.5锁和主题:

获取锁( System.Threading.Monitor.Enter 或进入一个synchronized方法)将隐式执行挥发性的读操作,并释放锁( System.Threading.Monitor.Exit 或离开一个synchronized方法)将隐式执行挥发性的写操作。见§12.6.7。

Acquiring a lock (System.Threading.Monitor.Enter or entering a synchronized method) shall implicitly perform a volatile read operation, and releasing a lock (System.Threading.Monitor.Exit or leaving a synchronized method) shall implicitly perform a volatile write operation. See §12.6.7.

12.6.7挥发性读取和写入:

一个动荡读了收购语义,这意味着在读的保证之前,内存中的CIL指令序列读取指令之后发生的任何引用发生。挥发性写有释放语义,意思是写保证发生后,之前在CIL指令序列的写指令的任何内存引用。

A volatile read has "acquire semantics" meaning that the read is guaranteed to occur prior to any references to memory that occur after the read instruction in the CIL instruction sequence. A volatile write has "release semantics" meaning that the write is guaranteed to happen after any memory references prior to the write instruction in the CIL instruction sequence.

此外,这些博客文章有一些细节可能会感兴趣的:

Also, these blog entries have some details that might be of interest:

  • <一个href="http://blogs.msdn.com/jaredpar/archive/2008/01/17/clr-memory-model.aspx">http://blogs.msdn.com/jaredpar/archive/2008/01/17/clr-memory-model.aspx
  • <一个href="http://msdn.microsoft.com/msdnmag/issues/05/10/MemoryModels/">http://msdn.microsoft.com/msdnmag/issues/05/10/MemoryModels/
  • <一个href="http://www.bluebytesoftware.com/blog/2007/11/10/CLR20MemoryModel.aspx">http://www.bluebytesoftware.com/blog/2007/11/10/CLR20MemoryModel.aspx
  • http://blogs.msdn.com/jaredpar/archive/2008/01/17/clr-memory-model.aspx
  • http://msdn.microsoft.com/msdnmag/issues/05/10/MemoryModels/
  • http://www.bluebytesoftware.com/blog/2007/11/10/CLR20MemoryModel.aspx

这篇关于难道Monitor.Wait确保字段是重读?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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