zoukankan      html  css  js  c++  java
  • volatile

    volatile具备的两种特性:

      1、可见性

      2、禁止指令重排

    解析:

      1、可见性:用volatile修饰的变量,会使线程在使用该变量时,每次都从主内存中读取到工作内存,再使用。

        对比普通的变量,线程在使用时,如果工作内存中没有该变量,则先从主内存中拷贝,在使用。如果工作内存中已经存在了该变量,则不再从主内存中重新读取。

      volatile变量,由于每次都从主内存中先同步,再使用。由此来保证可见性。

      2、禁止指令重排:用volatile修饰的变量,会使线程在使用变量的时候,禁止指令重排。

        对比普通的变量,线程在使用时,如果存在两处赋值,而这两处赋值对于后续的计算没有影响,那么可能由于优化的原因,而进行指令重拍。

      举例:单例模式(双检锁实现)

      public class Singleton{

        private static Singleton instance;//定义一个单例

        public static Singleton getInstance(){

          if ( instance == null ) {

             synchronized(Singleton.class){

                if( instance == null ){

                  instance = new Singleton();

                }

             }      

          }

        }

        private Singleton(){} //私有构造方法

      }

      指令重排,在 instance = new Singleton();这一句中,有可能线程A还未完成全部的初始化工作,就已经将结果赋值给了instance这个变量。

      此时:线程B执行第一个if ( instance == null ) 判断,获取到对于的instance实例,在执行该实例对于的方法时,会由于实例未完成初始化工作,而导致异常。

    因此:需要将instance变量,定义为volatile类型。

    变量可见性的保证,还有另外两种方式:synchronized,final。

      synchronized:加锁后,一次只能有一个线程访问变量,而且每次放完变量后,需要unlock变量,变量才能被其它线程使用,因此能保证可见性。

      final:final的不变性,保证可见性。

    synchronized 与 volatile 的区别是,volatile不保证原子性,所以不是线程安全的。

  • 相关阅读:
    函数地址经典基础C++笔试题(附答案)
    类型事务修改 mysql 表类型 实际测试可执行
    ARM7,ARM9有哪些区别
    I2C,SPI,UART总线的区别详解
    I²C
    AnyWhere——面向设备的编程模式
    Linux设备驱动编程之内存与I/O操作
    http://www.ibm.com/developerworks/cn/linux/lcnspidermonkey/index.html
    PCI Express总线接口板的设计与实现
    armfans文章搜集
  • 原文地址:https://www.cnblogs.com/chen--biao/p/9801218.html
Copyright © 2011-2022 走看看