В Java остальные базовые переменные атомарны, за исключением 8-байтных, 64-битных переменных Long и Double.
Модель хранения Java требует, чтобы операции получения и сохранения были атомарными, но для энергонезависимых длинных и двойных переменных JVM позволяет разделять 64-битное чтение или запись на две 32-битные операции.
Если чтение и запись происходят по разным потокам, чтение длинного типа энергонезависимого типа может привести к высоким 32 битам одного значения и низким 32 битами другого.
Так что даже если вас не волнуют просроченные данные, использование общих, изменяемых длинных и двойных переменных в многопотоковой программе может быть небезопасно, если они не объявлены волатильными или защищены блокировкой.
Говоря об атомарных операциях, это означает, что чтение и запись атомарны, например, i=5; Это атомная операция.
Однако если операция двух атомов выполняется одновременно, она не обязательно атомарна, например, сначала чтение, а затем запись, то возможно, что переменная была изменена после чтения.
i++ — это такая операция: сначала читаешь, а потом записываешь, поэтому целочисленная переменная атомарна, а не то, что i++ — атомарная операция.
Когда вы используете for(int i=0; i<10000; i++){System.out.print(i)}
Вы обнаружите, что в итоге я не напечатаю 10 000, а напечатаю около 8-9 тысяч.
Но в случае многопоточности, даже если целочисленная переменная атомарна, могут возникнуть проблемы с безопасностью потока, что связано с видимостью потоков, поэтому нужно добавить волатильный оператор.
Этот модификатор — принудительная переменная, которая считывается из памяти каждый раз и не хранится в регистрах. |