Джо Даффи, дает 6 правил, описывающих модель памяти CLR 2.0+ (это фактическая реализация, а не какой-либо стандарт ECMA). Я записываю свою попытку выяснить это, главным образом как резиновая утка, но если я ошибусь в своей логике, то, по крайней мере, кто-то здесь сможет поймать ее, прежде чем она вызовет у меня горе.
- Правило 1: зависимость данных от нагрузок
и магазины никогда не нарушаются.
- Правило 2: Все магазины имеют семантику выпуска,
то есть ни груз, ни магазин не могут двигаться после
один.
- Правило 3: Все летучие нагрузки
приобретать, то есть не загружать или хранить
двигаться до одного.
- Правило 4: без нагрузки и
магазины могут когда-либо пересечь полный барьер
(например, Thread.MemoryBarrier, блокировка
приобрести, заблокирован. обмен,
Interlocked.CompareExchange и др.).
- Правило 5: загружать и складировать в кучу
никогда не может быть введен.
- Правило 6:
Грузы и магазины могут быть удалены только
при объединении смежных нагрузок и
магазины в том же месте.
Я пытаюсь понять эти правила.
x = y
y = 0 // Cannot move before the previous line according to Rule 1.
x = y
z = 0
// equates to this sequence of loads and stores before possible re-ordering
load y
store x
load 0
store z
Глядя на это, кажется, что нагрузка 0 может быть перемещена до до нагрузки y, но хранилища могут вообще не переупорядочиваться. Следовательно, если поток видит z == 0, он также видит x == y.
Если у был энергозависимым, то нагрузка 0 не могла двигаться до нагрузки у, иначе это может произойти. Волатильные магазины, похоже, не обладают какими-либо особыми свойствами, ни один магазин не может быть переупорядочен по отношению друг к другу (что является очень сильной гарантией!)
Полные барьеры похожи на линию в песке, по которой грузы и склады нельзя перемещать.
Понятия не имею, что означает правило 5.
Полагаю, правило 6 означает, что вы делаете:
x = y
x = z
Тогда CLR может удалить как загрузку в y, так и первое сохранение в x.
x = y
z = y
// equates to this sequence of loads and stores before possible re-ordering
load y
store x
load y
store z
// could be re-ordered like this
load y
load y
store x
store z
// rule 6 applied means this is possible?
load y
store x // but don't pop y from stack (or first duplicate item on top of stack)
store z
Что, если у летучий? Я не вижу в правилах ничего, что запрещало бы выполнение вышеуказанной оптимизации. Это не нарушает двойной проверки блокировки, поскольку lock () между двумя одинаковыми условиями предотвращает перемещение грузов в смежные позиции, и, согласно правилу 6, это единственный раз, когда они могут быть устранены.
Так что я думаю, что понимаю все, кроме правила 5, здесь. Кто-нибудь хочет просветить меня (или исправить меня, или добавить что-нибудь к чему-либо из вышеперечисленного?)