volatile关键字仅能用来修饰变量,能用来保证变量在线程间的可见性,同时能避免指令重排保证有序性,但是不能保证原子性。
有以下代码:
/**
* @Author shenxy
* @Date 2022/7/24 17:57
* @Version 1.0
*/
public class MyTest {
public volatile static int num = 0;
public static void main(String[] args) throws InterruptedException {
ExecutorService threadPool = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
threadPool.execute(() -> {
for (int j = 0; j < 10000; j++) {
num++;
}
});
}
// 等待1.5秒,保证上面程序执行完成
Thread.sleep(1500);
System.out.println(num);
threadPool.shutdown();
}
}
运行该代码,理论上输出值应为50000,但是实际结果却每次都小于50000。这是为什么呢?
首先要明白一点,num++是非原子性的操作。它分为三步进行执行:
- 将主存中 num 的值load到寄存器中
- num 的值在寄存器中自增
- 将自增后的值刷回主存
在变量 num 从主存被load到寄存器这一过程,如果 num 发生了变化,因为线程间的可见性,会重新去主存读取最新的 num 。但是,当 num 被加载到寄存器后,主存中 num 的值再发生变化,不会对寄存器内的 num 值造成影响。
由以上可以得知volatile不能保证原子性。
© 版权声明
THE END
暂无评论内容