首先明确几个概念:

        相对新值:一个线程更新了某共享变量的值之后,其他线程能够读取到这个更新后的值,那么这个值就被称为该变量的相对新值。

        最新值:如果读取了这个共享变量的线程在使用这个共享变量的过程中其他线程无法更新该变量的值,那么该项成读取到的值被称为该变量的最新值。

    volatile关键字用于修饰共享可变变量,即没有使用final关键字修饰的实例变量或静态变量,表示该变量"不稳定",易被修改。

    volatile能够保证可见性和有序性,以及读写long/double型变量操作的原子性。

    1.可见性

        对volatile变量的读写操作都必须从高速缓存或主内存中读取,以读取该变量的相对新值。换句话说,编译器不会为volatile变量分配寄存器存储,对volatile变量的读写操作都是内存访问操作(访问高速缓存相当于主内存)。

    读取一个volatile修饰的变量会使相应的处理器执行刷新处理器缓存的动作;写一个volatile关键字修饰的变量会使相应的处理器执行冲刷处理器缓存的动作。

    对于volatile变量的读操作,JVM会在该操作之前插入一个加载屏障,并在该操作之后插入一个获取屏障。

volatile关键字

    加载屏障通过冲刷处理器缓存,使其执行线程所在的处理器将其他处理器对共享变量(可能是多个变量)所做的更新同步到该处理器的高速缓存中。读线程执行的加载屏障和和写线程的存储屏障配合在一起使得写线程对volatile变量的写操作以及在此之前所执行的其他操作的结果对读线程可见,即保障了可见性

    2.有序性

        对于volatile变量的写操作,JVM会在该操作之前插入一个释放屏障,并在该操作之后插入一个存储屏障。

volatile关键字

        释放屏障禁止了volatile写操作与该操作之前的任何读、写操作进行重排序,从而保证了volatile写操作之前的任何读写操作会先于volatile变量写操作被提交,即其他线程看到写线程对volatile变量的更新时,写线程在更新volatile变量之前所执行的内存操作的结果对于读线程是可见的。这就保证了读线程对写线程在更新volatile变量之前对共享变量所执行的更新操作的感知顺序与相应的源代码一致,即保证了有序性。

    3.以及读写long/double型变量操作的原子性    

        对volatile变量的赋值操作,其右边表达式中只要涉及共享变量(包括被赋值的volatile变量本身,如i++),那么这个赋值操作就不是原子操作。

相关文章:

  • 2021-09-14
  • 2019-12-31
猜你喜欢
  • 2022-02-17
相关资源
相似解决方案