volatile

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++是非原子性的操作。它分为三步进行执行:

  1. 将主存中 num 的值load到寄存器中
  2. num 的值在寄存器中自增
  3. 将自增后的值刷回主存

在变量 num 从主存被load到寄存器这一过程,如果 num 发生了变化,因为线程间的可见性,会重新去主存读取最新的 num 。但是,当 num 被加载到寄存器后,主存中 num 的值再发生变化,不会对寄存器内的 num 值造成影响。

由以上可以得知volatile不能保证原子性。

© 版权声明
THE END
请撒泡尿证明你到此一游
点赞1 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容