Joe Duffy дает 6 rules that describe the CLR 2.0+ memory model (это реальная реализация, а не стандарт ECMA) Я пишу свою попытку понять это, в основном, как способ резинового уклона, но если я ошибаюсь в моя логика, по крайней мере, кто-то здесь сможет поймать ее, прежде чем это вызовет мое горе.Общие сведения о модели памяти CLR 2.0
- Правило 1: Зависимость данных между грузами и магазины не нарушаются.
- Правило 2: Все магазины имеют семантику выпуска, i.e. Без груза или магазина может перемещаться после .
- Правило 3: Все летучие грузы: приобретают, то есть нет груза или магазина могут перемещаться до одного.
- Правило 4: Нет нагрузки и магазинов никогда не может пересечь полный барьер (например Thread.MemoryBarrier, блокировка ACQUIRE, Interlocked.Exchange, 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 может быть перемещен до, прежде чем нагрузки у, но в магазинах не могут быть повторно заказать все. Поэтому, если поток видит z == 0, то он также увидит x == y.
Если y было изменчивым, тогда загрузка 0 не могла перемещаться перед загрузкой y, иначе это может произойти. У летучих магазинов нет особых свойств, никакие магазины не могут быть переупорядочены по отношению друг к другу (что является очень сильной гарантией!)
Полные барьеры похожи на линию на песке, которая загружает и хранит нельзя переместить.
Не знаю, что означает правило 5.
Я думаю, правило 6 означает, что если вы делаете:
x = y
x = z
Тогда можно для CLR, чтобы удалить и нагрузку у и первый магазин в х.
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
Что делать, если y была изменчивой? Я не вижу ничего в правилах, которые запрещают выполнение вышеуказанной оптимизации. Это не нарушает блокировку с двойной проверкой, поскольку блокировка() между двумя идентичными условиями предотвращает перемещение грузов в смежные позиции, и согласно правилу 6 это единственный раз, когда они могут быть устранены.
Итак, я думаю, что я понимаю все, кроме правила 5, здесь. Кто-нибудь хочет просветить меня (или исправить меня или добавить что-нибудь к любому из вышеперечисленных?)
Приятное объяснение! Это объясняет, почему вы не хотите, чтобы CLR вводил нагрузки. Я не могу придумать, где компилятор/JIT может когда-нибудь захотеть представить магазины, не так ли? – Eloff
Хорошо заслуженный +1. – Steven
@ Eloff: Некоторые компиляторы могут переписать «if (cond) {x = y;}» как «x = y», если (! Cond) {x = old_x;} ", если они считают, что лучше было бы предсказать ветвь. Несмотря на отсутствие заметной разницы в однопоточном сценарии, это, очевидно, имеет плохие последствия, если «x» отображается для нескольких потоков, поэтому модель памяти CLR запрещает это. –