volatile原理
- 可见性实现
- 修改volatile变量时会强制将修改后的值刷新的主内存中
- 修改volatile变量后会导致其他线程工作内存中对应的变量值失效。因此,再读取该变量值的时候就需要重新从读取主内存中的值。
- 有序性实现
-
记录 第二次操作 第一次操作 普通读/写 volatile读 volatile写 普通读/写 NO volatile读 NO NO NO volatile写 NO NO - 内存屏障:实现volatile可见性和happen-befor的语义。JVM底层是通过一个叫做“内存屏障”的东西来完成。也叫做内存栅栏,是一组处理器指令,用于实现对内存操作的顺序限制。下面是完成上述规则所要求的内存屏障
(1)LoadLoad 屏障
执行顺序:Load1—>Loadload—>Load2
确保Load2及后续Load指令加载数据之前能访问到Load1加载的数据。
(2)StoreStore 屏障
执行顺序:Store1—>StoreStore—>Store2
确保Store2以及后续Store指令执行前,Store1操作的数据对其它处理器可见。
(3)LoadStore 屏障
执行顺序: Load1—>LoadStore—>Store2
确保Store2和后续Store指令执行前,可以访问到Load1加载的数据。
(4)StoreLoad 屏障
执行顺序: Store1—> StoreLoad—>Load2
确保Load2和后续的Load指令读取之前,Store1的数据对其他处理器是可见的。
Required barriers | 2nd operation | |||
1st operation | Normal Load | Normal Store | Volatile Load | Volatile Store |
Normal Load | LoadStore | |||
Normal Store | StoreStore | |||
Volatile Load | LoadLoad | LoadStore | LoadLoad | LoadStore |
Volatile Store | StoreLoad | StoreStore |
package com.paddx.test.concurrent;
public class MemoryBarrier {
int a, b;
volatile int v, u;
void f() {
int i, j;
i = a;
j = b;
i = v;
//LoadLoad
j = u;
//LoadStore
a = i;
b = j;
//StoreStore
v = i;
//StoreStore
u = j;
//StoreLoad
i = u;
//LoadLoad
//LoadStore
j = b;
a = i;
}
}