Эрик, я прочитал ваши комментарии, и один из них меня особенно поразил
На самом деле я могу понять использование volatile на концептуальном уровне.Но для практики я не могу придумать код, который имеет проблемы с параллелизмом, без использования volatile
Очевидная проблема, с которой вы можете столкнуться, - это переупорядочивание компилятора, например, более известное поднятие, как упомянул Саймон Никерсон.Но давайте предположим, что никаких переупорядочений не будет, этот комментарий может быть действительным.
Другая проблема, которую решает volatile, связана с 64-битными переменными (long, double).Если вы записываете в long или double, это рассматривается как два отдельных 32-битных хранилища.Что может случиться с параллельной записью, так это то, что старшие 32 из одного потока записываются в старшие 32 бита регистра, а другой поток записывает младшие 32 бита.Тогда у вас может быть long, который не является ни тем, ни другим.
Кроме того, если вы посмотрите на раздел памяти JLS, вы увидите, что это модель расслабленной памяти.
Тоозначает, что записи могут некоторое время не отображаться (могут находиться в буфере хранилища).Это может привести к устареванию чтения.Теперь вы можете сказать, что это кажется маловероятным, и это так, но ваша программа неверна и может потерпеть неудачу.
Если у вас есть int, который вы увеличиваете на протяжении жизни приложения, и вы знаете (или хотя бы думаете), что int не переполнится, то вы не обновите его до long, но это все еще возможнооно может.В случае проблемы видимости памяти, если вы думаете, что это не должно влиять на вас, вы должны знать, что это все еще может и может вызвать ошибки в вашем параллельном приложении, которые чрезвычайно трудно идентифицировать.Правильность является причиной использования летучих.