1.static : 标识这个属性是实例共享的。(也可以称作类变量)
2.volatile:标记该属性是易变的,被修饰的属性被修改后,别的线程每当用到该属性都要重新去读取。
线程运行时会将用到的数据拷贝一份,放到自己的线程栈中,volatile会让该线程修改数据后写回原数据,并通知别的线程重新读取。
疑惑:static 修饰变量是类变量,被修改后别的线程也“应该”能读取到,是不是也具有线程可见性?
证明:代码如下
package highconcurrency;
/**
* <b>测试volatile关键字</b></br>
*
* @Company 子虚</ br>
* @Version V1.0
* @Author 花月
* @Date 2020/8/13 8:46
*/
public class TestVolatile {
public static void main(String[] args) {
MyData myData = new MyData();
new Thread(() -> {
System.out.println("线程启动a值为:"+myData.a);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
myData.changeA();
System.out.println("线程结束a值为:"+myData.a);
}).start();
//如果读取不到最新a值这里会死循环
while (myData.a==0){
//循环里不能写代码,不然不增加volatile也能读取最新的a值,猜想这里的操作导致while循环重新读取了a的值
/* try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
// System.out.println(myData.a);
}
System.out.println("a的值改变,并且被主线程看到");
}
}
class MyData{
//设置 volatile,static,和不加关键字。只有volatile能达到线程可见性。
// static int a = 0;
volatile int a = 0;
// int a = 0;
void changeA(){
a = 10;
}
}
当a属性不加static和volatile修饰时执行结果:
增加volatile关键字执行结果:
增加static修饰执行结果:
结论:
只有volatile具有线程可见性。
测试的时候while循环里不能写代码,写代码会导致不加volatile修饰出现和加volatile一样的效果.可能循环里的操作,导致重新读取a得值了。哪位大佬清楚这里原因请告知,不胜感激。