Java基础 - volatile

volatile的作用:对与volatile修饰的变量,

1,保证该变量对所有线程的可见性。

2,禁止指令重排序。

Java内存模型(JMM)

原子性

i = 2; 把i加载到工作内存副本i,副本i=2,把 副本i 刷回主存。是原子的。

j = i;  从主存读 i和j 的副本到工作内存,把副本j=副本i,把副本j刷回主存。不是原子的。

i++;  即i=i+1;从主存读i的副本到工作内存,把副本i的值自增1,把副本i写回主存。不是原子的。

可见性

当一个变量被volatile修饰时,那么对它的修改会立刻刷新到主存,当其它线程需要读取该变量时(对于一条指令只读一次,比如i=i+1,读一次i;而while(flag) 每次判断只读一次,循环3次则读3次。这一点有助于理解volatile保证可见性却对非原子操作的指令i++无效),会去主存中读取最新值。

有序性

double pi = 3.14;//A

double r = 1; //B

double s= pi * r * r;//C

由于不会影响结果,JMM会对指令重排序,所以执行顺序可能是ABC,也可能是BAC,只要在单线程时不会影响结果。

假设某一指令有volatile变量,则该指令前的所有指令必然在该指令前执行,该指令后的所有指令必然在该指令后执行。

int a = 0;
bool flag = false;

public void write() {
    a = 2;              //1
    flag = true;        //2
}

public void multiply() {
    if (flag) {         //3
        int ret = a * a;//4
    }
}
View Code

假设线程1执行write,线程2执行multiply,ret的结果不一定是4.

 如何保证i++原子性

1,syncronized,lock等(悲观锁)

2,CAS(乐观锁,比如使用AtomicInteger)

---

参考:

https://juejin.im/post/5a2b53b7f265da432a7b821c

https://www.cnblogs.com/zhengbin/p/5654805.html

猜你喜欢

转载自www.cnblogs.com/lankerenf3039/p/12032905.html