Volitale

原理

可见性

可见性(visibility):是指一个线程对共享变量进行修改,另一个线程立即得到修改后的最新值

写屏障保证在改屏障之前的,对共享变量的改动都同步到主存中

读屏障保证该屏障之后,对共享变量的读取,加载的是最新的数据

class Main{
    volatile boolean ready;
    //写屏障
    public void a1(){
        ready=true;
    }
    //读屏障
    public void a2(){
        if(ready){
            System.out.println("true");
        }
    }
}

有序性

有序性(Ordering):是指程序员中代码执行的顺序,就是程序最终的运行顺序

写屏障能保证写屏障之前的代码,不会进行指令重排序到后面

读屏障能保证读屏障之后的代码不会进行指令重排序到前面

提示

  • volitale只能保证可见性和有序性,并不能保证原子性(synchronized可以做到)
  • 有序性也是只保证了本线程内的代码不会被重排序

CAS

cas 比较并交换可以实现无锁的并发

其实底层代码的实现是用的乐观锁

volatile

获取共享变量时,为了保证该变量的可见性,需要用volatile修饰

它可以用来修饰成员变量和静态成员变量,它可以避免线程从自己的工作缓存中查找变量的值,必须到驻村中获取它的值,线程操作volatile变量都是直接操作主存.即一个线程对volatile变量的修改,对另一个线程是可见的.

注意

volatile仅仅是保证了共享变量的可见性,让其他线程能够看到最新值,但不能解决指令交错的问题(不确保原子性)

cas必须借助volatile才能读取到共享变量的最新值来实现比较并交换的效果

AtomicInteger中的value属性是这样定义的

private vlatile int value;

DCL问题

著名的doble-checked locking单例模式为例 (双检查的锁模式1.5之后才可以)

class Main{
    private static Main main;
    private Main(){};
    public static Main getMain() {
        //在synchronized外面加一个判断是防止代码每次都进入synchronized保证效率
        if (main==null){
            synchronized (Main.class){
                if (main==null){
                    main = new Main();
                }
            }
        }
        return main;

    }
}

其实在多线程环境下上面代码是有问题的

main = new Main();不是一个原子性操作,做了以下的操作

  • 创建一个对象,将对象引用入栈
  • 复制一份对象的引用
  • 利用对象的引用调用构造方法
  • 利用对象的引用赋值给static main

也许jvm会优化为,先将对象的引用赋值,再调用构造方法

synchronized只有完全保护一个变量,才能解决原子性,可见性,有序性问题,而上面的例子没有完全保护该变量

解决方法

class Main{
    private volatile static Main main;//加上volatile
    private Main(){};
    public static Main getMain() {
        //在synchronized外面加一个判断是防止代码每次都进入synchronized保证效率
        if (main==null){
            synchronized (Main.class){
                if (main==null){
                    main = new Main();
                }
            }
        }
        return main;

    }
}

对volitale读取操作之前会加上读屏障,而在volatile写操作之后会加上写屏障.

读屏障能保证读屏障之前的代码跑到后面去

写屏障保证写屏障之后的代码跑到前面去

Last modification:July 29, 2022
如果觉得我的文章对你有用,请随意赞赏