>> (x) Случай Vx,Ax. Может ли в этом случае компилятор закэшировать значение переменной? Имеются в виду как обычные, так и наиболее агрессивные настройки оптимизации. >> Итого, соотв, 4 варианта.
ME>Не будет закэшировано во всех вариантах. (если, конечно, никто не применит ключ компиляции "компайлер, здесь нет никакого альясинга, мамой клянусь!")
Заметьте, я говорил как про обычную, так и агрессивную оптимизацию. Итак, вы все-таки признаете, что при включенной агрессивной оптимизации возможны проблемы. Например, вычисление значение переменной заранее, и затем использование его после внешнего изменения этого значения (пример, кстати, вам привел emusic). В случае с простыми interlocked, это, конечно, довольно сложно представить (но наверняка придумать пример можно), но как только в дело вступают критические секции, которые никак не позиционируют себя по отношению к объекту, который охраняют, ситуация усложняется.
Тогда немного переформулируем вопрос. При условии того, что для синхронизации используются стандартные функции\примитивы синхронизации, предоставляемые ОС, использование volatile в определении разделяемой переменной:
а) бесполезно во всех случаях — компилятор генерирует неоднозначный код при агрессивной оптимизации в любом случае
б) способно помочь компилятору даже при агрессивной оптимизации сделать предположения о внешнем изменении переменной и таки не кешировать ее значение либо в регистре, либо константно (например, вычисляя его заранее исходя из условия)
с) способно ухудшить ситуацию — компилятор может при наличии volatile сгенерировать неоднозначный код там, где этого без volatile не наблюдалось.
Соответственно, выбрать можно любой из пунктов (или несколько сразу) + придумать свои вариант, ессно, обосновав ответ.
Для себя я, как уже говорил, выбираю б), поскольку не вижу минусов при указании подобным переменным спецификатора volatile. Оптимизировать доступ к ним обычно и не требуется, а плюсы, хоть редко, но быть могут, как уже было показано. С вариантом с) я никогда не встречался.