• volatile理解


    多线程程序常考虑三种性质:原子性、可见性、有序性。定义如下:

     1. 原子性:
           一个或多个操作的执行,只有两种情况:(1)全部执行并且执行过程中不会被打断;(2)不执行
     2. 可见性:
            当多个线程访问同一个共享变量时,一个线程修改了变量的值,其他线程能够立即看到被修改的新值。 例如:
                 //线程1执行的代码  
                    int i = 0;  
                    i = 10;  
                 //线程2执行的代码  
                    j = i;

            当线程1执行完i=10时,其过程是:将i的初始值读入高速缓存中,然后讲高速缓存中 i 的值改为10,再将i的新值刷入内存中;

            若没有可见性,则i的新值未刷入主存时,线程2执行,此时线程2读取内存中的 i 的值为0。(线程1修改了 i 值,线程2没有立即看到)

     3. 有序性:

            程序执行的顺序按照代码中的先后顺序执行。

            为了提高程序效率,编译器会对代码进行优化,将没有依赖关系的指令执行先后顺序进行重排,使指令执行顺序与代码先后顺序不同,但保 证最终的结果一致。虽然指令重排对单线程没有影响,但会影响多线程并发执行的正确性。

    在JAVA中实现三种性质的方式:

       原子性是通过同步(Synchronized或Lock锁机制)来实现;

           可见性是通过volatile来实现(保证变量修改后立即写入内存);

           有序性是通过同步或volatile来实现。

    volatile的特性与作用:

     1. volatile修饰变量后的特性:

              (1)保证了多个线程对变量操作的可见性,即:一个线程修改了变量值,其他线程立即可见。(保证变量安全,不保证线程安全)

              (2)禁止进行指令重排。(防止编译器自动优化,对代码顺序的指令重新排序)    

     2. volatile保证变量可见性:

              (1)使用volatile修饰的变量,在一个线程中被修改后会强制立即写入内存(不经过线程工作内存,即线程中的寄存器或堆栈空间);

              (2)使用volatile修饰的变量,当有线程修改其值后,其他线程的工作内存中该值无效;

              (3)使用volatile修饰的变量,所有线程必须从内存读取变量值(不经过线程工作内存,即该线程的寄存器或堆栈空间)。  

     3. volatile不保证变量原子性:

               某些情况下,volatile可以实现变量原子性,如:long和double都是64位宽,32位操作系统对这种类型变量的读取分两部分,第一次读取32位,第二次读取剩下的32位。读取操作不是原子性的,当用volatile修饰(volatile long)时,可以将操作变为原子性操作。

     4. volatile保证变量有序性:

               使用volatile修饰的变量,编译器不能对该变量所在指令重排(例如:该指令之前的指令集合相互可以重排,但不能重排到该指令后面)

  • 相关阅读:
    RESTful API 介绍,设计
    golang web框架设计7:整合框架
    golang web框架设计6:上下文设计
    golang web框架设计5:配置设计
    golang web框架设计4:日志设计
    golang web框架设计3:controller设计
    golang web框架设计2:自定义路由
    golang web框架设计1:框架规划
    深入理解golang: channels
    服务端高并发分布式十四次架构演进之路
  • 原文地址:https://www.cnblogs.com/ladawn/p/8253531.html
Copyright © 2020-2023  润新知