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!)
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()?
Looking at reflector, Wait calls down into ObjWait, which is managed internalcall (the same as  Enter).
The scenario in question was:
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.
 
     
     
     
    