认识volatile关键字

简单记录自己理解的volatile关键字


简单概念

计算机执行程序时,每条指令都是由CPU执行的,指令的执行又涉及到数据的读取和写入。程序的临时数据是在主存(物理内存)中,频繁的读取和写入就会产生一个问题,从主存中读取和写入的时间要比CPU执行指令的时间要长的多,大大降低计算机的执行效率,于是CPU里就有了高速缓存。

i = i + 1;

比如上式,线程先将i值从主存读入高速缓存中,计算i+1,计算完成后再写回主存。

单线程时上面的计算和描述是没有问题的,如果两个线程同时执行这段代码,假如i的初始值是0,那么理论上我们期望得到i的值是2,真的 是这样吗?

有种情况可能得到的值是1,两个线程分别来读取i的值到缓存中,线程1计算完成后写入主存i=1,此时线程2中的i还是0,计算完成后i也是1,然后线程2将i=1写入主存。

最终结果i的值是1,而不是2。这就是著名的缓存一致性问题。通常称这种被多个线程访问的变量为共享变量。

并发编程的常见问题

1 . 原子性

举个栗子:i++, i=2, i=x+y 这三个操作中,其实只有i=2是原子操作,i++等价于i=i+1,就回到上面讲的那个问题了,看代码

    static int count = 0;

    public static void main(String[] args) throws InterruptedException {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    for (int i=0; i<10000; i++) {
                        increment();
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        };
        Thread thread1 = new Thread(runnable, "thread1");
        Thread thread2 = new Thread(runnable, "thread2");
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(count);
    }

    private static void increment(){
        count++;
    }

你会发现输出的值始终小于20000,原因之一是count++不是原子操作。

若想执行得到正确的值只需要使用synchronized关键字修饰increment()方法即可

private static synchronized void increment(){
    count++;
}

或者使用其他锁,比如ReentrantLock,还有AtomicInteger

2 . 可见性

上面的问题也说明了线程之间的缓存可见性

volatile关键字的作用之一就是使共享变量在缓存中被修改时,及时将数据刷入主存上,并通知其他线程该变量的缓存无效,需要重新在主存中读取

synchronized关键字和Lock也可以解决缓存不一致问题,因为synchronized只允许一个线程执行,所以就不存在可见性的问题了

3 . 有序性

java内存模型为了提高执行效率,会对指令进行重排序,不保证代码执行顺序和源代码一致,但保证代码执行结果和顺序执行结果一致。


volatile关键字的作用

1.保证可见性,即被volatile修饰的变量,在线程的高速缓存中被修改后,会及时刷入主存,并通知其他线程该变量的缓存失效,使用时重新在主存中读取

2.禁止进行指令重排序(即volatile修饰的变量,前面的指令不会被排到该变量后面,后面的一样不会被排带前面去)


记录一下,顺便帮助自己捋一遍思路,记录过程中发现自己也有很多概念模糊的地方,收获很多,关于volatile的文章,比我记录详细的文章很多,这篇文章主要为自己写。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值