美文网首页
Volatile用法和原理

Volatile用法和原理

作者: k55k55k55 | 来源:发表于2017-12-29 13:13 被阅读0次

    前言

      Volatile的关键字从Java5出现后就存在了,很多人做了很长时间的Java开发都未必用的到这个关键字,其实它还是很有用的一个关键字。

    正文

    简单概述

      volatile是Java提供的一种轻量级的同步机制,同synchronized相比,volatile更轻量级,在访问volatile变量时不会执行加锁操作,因此也就不会使执行的线程阻塞。

    变量不加volatile

    问题1 可见性问题

      CPU每次执行指令的时候会对内存进行读写操作,尽管内存的读写速度比硬盘的读写速度快得多,但是指令的处理速度更快,从内存进行读写速度相对于指令执行的速度就慢了,所以CPU就会将线程用到的变量以及一些复杂的操作复制到缓存(寄存器)中处理,然后再将处理的结果写入内存。但是对于多核CPU,线程可能运行在不同的CPU缓存中,这样的话就无法保证线程的可见性(指线程之间的可见性,一个线程修改的变量后,另一个线程取到变量也是修改后的变量)

    image.png
    //初始化
    int i =10;
    //每个线程都对i++
    i++;
    

      对于i来说,线程A从内存读取i后存入缓存,它取到的值是10,线程B也将i从内存中读入缓存,取到值也是10。线程A对i++,i就变成了11,但是线程B中的i还是10,那么i变量对于线程是不可见的了。

    问题2 有序性问题
    int i = 0;//A步骤
    int j = 1;//B步骤
    i++;//C步骤
    j++;//D步骤
    

      CPU为了保证性能或者在多个线程存在的情况下,对于指令的处理顺序会有变化(指令重排序:CPU允许将多条指令不按程序规定的顺序分别给各个相应的处理器处理),比如它可能先执行了B步骤,然后在执行A步骤,也可能先执行了D步骤,然后再执行C步骤。

    变量加volatile

    线程可见性
    //初始化
    volatile int i =10;
    

      对于一个变量赋予了volatile关键字后那么变量对所有的线程具有可见性,当一个线程修改了这个变量的值,编译器就不会将这个变量复制到缓存中,就直接在内存中操作,这样从内存中取到的volatile标识的变量就是最新的值,也就对其它线程可见了。


    image.png
    线程有序性

      volatile可以禁止指令重排序,volatile标识的变量,会有内存屏障,指令重排序时就不能把后面的指令重排序到内存屏障之前的位置,这样就保证不同的代码块只能串行执行,不能同步执行,这样就保证了线程的有序性。

    volatile缺点

    volatile不能保证原子性,volatile可以配合synchronized保证原子性。

    相关文章

      网友评论

          本文标题:Volatile用法和原理

          本文链接:https://www.haomeiwen.com/subject/bhcigxtx.html