volatile关键字
什么是可见性?
可见性是指线程A改变变量的值后,线程B可以马上看到更改后变量的值
volatile的作用
关键字volatile提示线程每次从共享内存中读取数据,而不是从私有内存中读取,这样就保证了同步数据的可见性
关键字volatile适用的场景
当想实现一个线程对一个变量进行修改,希望其他线程可以取到最新的值的时候。就需要对变量使用volatile关键字了
我们举一个例子:
import static java.lang.Thread.sleep;
public class VolatileTest {
public static boolean flag = true;
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(\"线程1 开始!\");
while(flag){
}
System.out.println(\"线程1 结束!\");
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(\"线程2 开始!\");
flag = false;
System.out.println(\"flag = \" + flag);
}
});
t1.start();
sleep(2000);
t2.start();
}
}
- 运行结果
我们可以看到:程序在一直运行,进入了死循环,那么是什么原因造成出现了死循环呢?
- 我么在启动线程t1之后,变量“public static boolean flag = true;”存在于公共堆栈及线程私有的堆栈中,
t1运行后一直在线程私有堆栈中取得的flag的值是true,而线程2的代码“flag = false;”,修改的是公共堆栈中的
flag,所以t1线程私有堆栈中的flag仍然是true。
解决方法 -添加volatile关键字
修改“public static volatile boolean flag = true;”,我们再次运行程序
volatile是否具有原子性?
关键字volatile最大的缺点是不支持原子性,如果修改实例中的数据,比如i++,这样的操作不是原子操作,分为三步
- 从内存中取i的值
- 计算i的值
- 将i的值存入内存中
如果在第二步计算i的值时,其他线程读取i的值,并对i进行修改,这个时候就会出现脏数据,解决方法是使用synchronized关键字
- 参考资料《Java多线程编程核心技术 第二版》
来源:https://www.cnblogs.com/classicltl/p/16224918.html
本站部分图文来源于网络,如有侵权请联系删除。