volatite的使用有几点需要注意。
一.对写入变量的写入操作不依赖当前值
如 num++,num=num*2
这是因为volatite它只有可见性,却不满足原子性。
num++可分解为
1 取num
2 num +1 加法操作
3 num=num 赋值操作
因不满足原子性,例如num=1。当线程a 执行到2加法操作时。线程b执行到3赋值操作。由于是volatite所以立即写入内存。
此时num=2。切换到线程a 继续执行3赋值操作时,Num还是等于。
当然,对于boolean变量是满足的。一般来说,Boolean只对它进行赋值操作。只有一步操作。并且是volatite,所以一赋值完就写入内存。对其他线程可见。
二. 该变量没有包含在具有其他变量的不变式中
不满足:不变式low<up
这里面有两个VOLATILE变量,它包含了一个不变式就是LOW<UP( if (value > upper) 和 if (value < low) )
public class A {
private volatile int low=0;
private volatile int up=100;
public int getLow() { return low; }
public int getUp() { return up; }
public void setLow(int value) {
if (value > upper)
system.out.print(".......");
low = value;
}
public void setUp(int value) {
if (value < low)
system.out.print(".......");
up = value;
}
}
初始值是0和100,如果有两个线程同时操作set函数,一比如A线程操作setlow(4),B线程setup(3),最后结果是4和3。
原因当然还是因为原子操作的问题。
线程a执行setLow 并执行到 if (value > upper) 马上切换线程b执行setup 执行到 if (value < low)
这两个线程都进入了if判断语句内,错误就很显而易见了。
三.为什么用volatite
看了volatite那么多不适用的地方,有人肯定会想怎么不用synchronized。synchronized满足原子性,又满足可见性。正事因为synchronized满足原子性,你想想,你要把它的代码全部执行完,才能切换进程,当然会慢很多。
所以为了提高性能当然用volatite。毕竟多线程就是来提高性能的。