并发和多线程(十三)--volatile关键字

volatile:

  相当于轻量级的synchronized,因为不存在线程上下文切换这种消耗很大的操作,volatile的读写都是无锁的操作,但是应用范围相对较少,volatile一般用来修饰变量。

volatile不能保证原子性:

  在之前的博客有说到,通过Atomic相关类、synchronized、lock等都能够实现原子性,也就是共享变量的访问互斥,但是volatile无法保证原子性。volatile符合happens-before原则,所以具有可见性和有序性。

volatile保证可见性: 

  1、通过加入内存屏障来实现

  2、对volatile变量进行读写操作,都会通过store、load来强制从主存中读取最新的值,或将数据强制刷新到主存中。

volatile保证有序性:

  通过禁止指令重排保证有序性。

volatile使用场景:

  1.不适合计数场景:因为无法保证原子性。

  3.适合作为状态标示量:例如多线程下作为boolean类型的flag,但是必须只是单纯被多个线程赋值,不能包含其他的操作,如flag = true;如果依赖之前的结果,这样同样不是线程安全,如flag = !flag。

  3.作为触发器:volatile修饰的变量放在后面,之前的所有操作都是具有可见性的,然后变量作为条件判断,实现触发器的作用。

  4.doubleCheck:

单例doubleCheck实现:

public class SingletonExample {

    // 私有构造函数
    private SingletonExample() {

    }
   //分配内存一共有三步
    // 1、memory = allocate() 分配对象的内存空间
    // 2、ctorInstance() 初始化对象
    // 3、instance = memory 设置instance指向刚分配的内存

    // 单例对象 volatile + 双重检测机制 -> 禁止指令重排
    private volatile static SingletonExample instance = null;

    // 静态的工厂方法
    public static SingletonExample getInstance() {
        if (instance == null) { // 双重检测机制
            synchronized (SingletonExample.class) { // 同步锁
                if (instance == null) {
                    instance = new SingletonExample();
                }
            }
        }
        return instance;
    }
}

posted @ 2019-05-16 17:07  Diamond-Shine  阅读(194)  评论(0编辑  收藏  举报