Hello, I was measuring costs of hoisting volatile access out of the loop and found out, that there's a difference in numbers for arrays and "plain" references.
Here's the benchmark for array: @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) @Warmup(time = 2, iterations = 5) @Measurement(time = 2, iterations = 5) @Fork(value = 4, jvmArgs = "-Xmx1g") public class VolatileArrayInLoopBenchmark { @Benchmark public int accessVolatileInLoop(Data data) { int sum = 0; for (int i = 0; i < data.count; i++) { sum += data.ints[i]; } return sum; } @Benchmark public int hoistVolatileFromLoop(Data data) { int sum = 0; int[] ints = data.ints; for (int i = 0; i < data.count; i++) { sum += ints[i]; } return sum; } @State(Scope.Benchmark) public static class Data { @Param({"1", "10", "100"}) private int count; private volatile int[] ints; @Setup public void setUp() { int[] ints = new int[count]; for (int i = 0; i < ints.length; i++) { ints[i] = ThreadLocalRandom.current().nextInt(); } this.ints = ints; } } } and this one is for reference: @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) @Warmup(time = 2, iterations = 5) @Measurement(time = 2, iterations = 5) @Fork(value = 4, jvmArgs = "-Xmx1g") public class VolatileFieldInLoopBenchmark { @Benchmark public int accessVolatileInLoop(Data data) { int sum = 0; for (int i = 0; i < data.count; i++) { sum += data.value; } return sum; } @Benchmark public int hoistVolatileFromLoop(Data data) { int sum = 0; int value = data.value; for (int i = 0; i < data.count; i++) { sum += value; } return sum; } @State(Scope.Benchmark) public static class Data { private final ThreadLocalRandom random = ThreadLocalRandom.current(); private volatile int value = random.nextInt(); @Param({"1", "10", "100"}) private int count; } } >From measurement results it looks like volatile array access is cheaper than >"plain" reference access: Java 19 Benchmark (count) Mode Cnt Score Error Units VolatileArrayInLoopBenchmark.accessVolatileInLoop 1 avgt 20 2.110 ± 0.404 ns/op VolatileArrayInLoopBenchmark.accessVolatileInLoop 10 avgt 20 14.836 ± 2.825 ns/op VolatileArrayInLoopBenchmark.accessVolatileInLoop 100 avgt 20 146.497 ± 25.786 ns/op VolatileArrayInLoopBenchmark.hoistVolatileFromLoop 1 avgt 20 3.006 ± 0.686 ns/op VolatileArrayInLoopBenchmark.hoistVolatileFromLoop 10 avgt 20 6.222 ± 1.215 ns/op VolatileArrayInLoopBenchmark.hoistVolatileFromLoop 100 avgt 20 33.262 ± 6.579 ns/op VolatileFieldInLoopBenchmark.accessVolatileInLoop 1 avgt 20 1.823 ± 0.382 ns/op VolatileFieldInLoopBenchmark.accessVolatileInLoop 10 avgt 20 10.259 ± 2.874 ns/op VolatileFieldInLoopBenchmark.accessVolatileInLoop 100 avgt 20 98.648 ± 18.500 ns/op VolatileFieldInLoopBenchmark.hoistVolatileFromLoop 1 avgt 20 2.189 ± 0.412 ns/op VolatileFieldInLoopBenchmark.hoistVolatileFromLoop 10 avgt 20 4.734 ± 0.891 ns/op VolatileFieldInLoopBenchmark.hoistVolatileFromLoop 100 avgt 20 7.126 ± 1.309 ns/op Java 20 Benchmark (count) Mode Cnt Score Error Units VolatileArrayInLoopBenchmark.accessVolatileInLoop 1 avgt 20 1.714 ± 0.066 ns/op VolatileArrayInLoopBenchmark.accessVolatileInLoop 10 avgt 20 10.703 ± 0.148 ns/op VolatileArrayInLoopBenchmark.accessVolatileInLoop 100 avgt 20 109.001 ± 1.866 ns/op VolatileArrayInLoopBenchmark.hoistVolatileFromLoop 1 avgt 20 2.408 ± 0.224 ns/op VolatileArrayInLoopBenchmark.hoistVolatileFromLoop 10 avgt 20 4.678 ± 0.060 ns/op VolatileArrayInLoopBenchmark.hoistVolatileFromLoop 100 avgt 20 24.711 ± 1.091 ns/op VolatileFieldInLoopBenchmark.accessVolatileInLoop 1 avgt 20 1.366 ± 0.105 ns/op VolatileFieldInLoopBenchmark.accessVolatileInLoop 10 avgt 20 7.388 ± 0.119 ns/op VolatileFieldInLoopBenchmark.accessVolatileInLoop 100 avgt 20 74.630 ± 1.163 ns/op VolatileFieldInLoopBenchmark.hoistVolatileFromLoop 1 avgt 20 1.653 ± 0.035 ns/op VolatileFieldInLoopBenchmark.hoistVolatileFromLoop 10 avgt 20 3.138 ± 0.040 ns/op VolatileFieldInLoopBenchmark.hoistVolatileFromLoop 100 avgt 20 4.945 ± 0.177 ns/op So my question is why is volatile reference access is relatively more expensive than volatile array access?