各位大神,请教一个问题,我今天在sonar上看到一个报警,非基础字段不建议用volatile修饰,内容如下:
我看网上的解释是volatile只是确保对象的引用地址可见。对象的成员变量是不可见的
参考:https://blog.csdn.net/u014674862/article/details/89168376(这里写的很好,学习了,但是这个问题没有得到解答)
public class Test implements Runnable{
private volatile ObjectA a;
public Test(ObjectA a) {
this.a = a;
}
public ObjectA getA() {
return a;
}
public void setA(ObjectA a) {
this.a = a;
}
@Override
public void run() {
long i = 0;
while (a.isFlag()) {
i++;
System.out.println("------------------");
}
System.out.println("stop My Thread " + i);
}
public void stop() {
a.setFlag(false);
}
public static void main(String[] args) throws InterruptedException {
System.out.println(System.getProperty("java.vm.name"));
Test test = new Test(new ObjectA());
new Thread(test).start();
test.stop();
System.out.println("Main Thread " + test.getA().isFlag());
}
static class ObjectA {
private boolean flag = true;
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
}
输出如下
Java HotSpot(TM) 64-Bit Server VM
Main Thread false
stop My Thread 0
发现成员变量是可见的,循环可以正常中断。
volatile修饰非基础类型,指的是每次刷新对象的引用。非基础数据类型,建议用AtomiXX代替volatile。
为什么会有这样的建议?实现不明白,既然成员变量是可见的,每次都分配了新的内存空间么,空间损耗吗?
对象型 用volatile刷新的是引用地址,不是对象内容本身。禁止了指令重排,对象内容改变happen-before于引用地址的刷新,那
我觉得也没有什么问题吧,这是我的理解。。。
实在想不出个所以然,请教一下各位,有清楚的,帮忙解答一下。多谢。