Общепринято (я верю!), Что lock
заставит перезагружать любые значения из полей (по сути, выступая в качестве барьера памяти или ограждения - моя терминология в этой области немного ослабла, я боюсь), в результате чего поля, которые когда-либо доступны только внутри lock
, сами по себе не обязательно должны быть volatile
.
(Если я уже не прав, просто скажите!)
Хороший комментарий был здесь поднят , спрашивающий, верно ли то же самое, если код выполняет Wait()
- то есть, если он был Pulse()
d, перезагрузит ли он поля из памяти, или они могли быть в реестре (и т. д.).
Или проще: нужно ли для поля volatile
гарантировать, что текущее значение будет получено при возобновлении после Wait()
?
Глядя на отражатель, 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
}
}
Очевидно, я мог бы просто сделать это volatile
, или я мог бы переместить это так, чтобы я выходил и снова вводил Monitor
каждый раз, когда он пульсирует, но я заинтригован, чтобы узнать, является ли любой из них необходимо .