• 这里还得提一个概念,as-if-serial

    as-if-serial

    不管怎么重排序,单线程下的执行结果不能被改变。

    编译器、runtime和处理器都必须遵守as-if-serial语义。

    那Volatile是怎么保证不会被执行重排序的呢?

    内存屏障

    java编译器会在生成指令系列时在适当的位置会插入内存屏障指令来禁止特定类型的处理器重排序。

    为了实现volatile的内存语义,JMM会限制特定类型的编译器和处理器重排序,JMM会针对编译器制定volatile重排序规则表:

    需要注意的是:volatile写是在前面和后面分别插入内存屏障,而volatile读操作是在后面插入两个内存屏障

    上面的我提过重排序原则,为了提高处理速度,JVM会对代码进行编译优化,也就是指令重排序优化,并发编程下指令重排序会带来一些安全隐患:如指令重排序导致的多个线程操作之间的不可见性。

    如果让程序员再去了解这些底层的实现以及具体规则,那么程序员的负担就太重了,严重影响了并发编程的效率。

    从JDK5开始,提出了happens-before的概念,通过这个概念来阐述操作之间的内存可见性。

    happens-before

    如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须存在happens-before关系。

    volatile域规则:对一个volatile域的写操作,happens-before于任意线程后续对这个volatile域的读。

    如果现在我的变了falg变成了false,那么后面的那个操作,一定要知道我变了。

    聊了这么多,我们要知道Volatile是没办法保证原子性的,一定要保证原子性,可以使用其他方法。

    无法保证原子性

    就是一次操作,要么完全成功,要么完全失败。

    假设现在有N个线程对同一个变量进行累加也是没办法保证结果是对的,因为读写这个过程并不是原子性的。

    要解决也简单,要么用原子类,比如AtomicInteger,要么加锁(记得关注Atomic的底层)。

    应用

    单例有8种写法,我说一下里面比较特殊的一种,涉及Volatile的。

    大家可能好奇为啥要双重检查?如果不用Volatile会怎么样?

    我先讲一下禁止指令重排序的好处。

    对象实际上创建对象要进过如下几个步骤:

    上面我不是说了嘛,是可能发生指令重排序的,那有可能构造函数在对象初始化完成前就赋值完成了,在内存里面开辟了一片存储区域后直接返回内存的引用,这个时候还没真正的初始化完对象。

    但是别的线程去判断instance!=null,直接拿去用了,其实这个对象是个半成品,那就有空指针异常了。

    可见性怎么保证的?

    因为可见性,线程A在自己的内存初始化了对象,还没来得及写回主内存,B线程也这么做了,那就创建了多个对象,不是真正意义上的单例了。

    上面提到了volatile与synchronized,那我聊一下他们的区别。

    volatile与synchronized的区别

    volatile只能修饰实例变量和类变量,而synchronized可以修饰方法,以及代码块。

    volatile保证数据的可见性,但是不保证原子性(多线程进行写操作,不保证线程安全);而synchronized是一种排他(互斥)的机制。volatile用于禁止指令重排序:可以解决单例双重检查对象初始化代码执行乱序问题。

    volatile可以看做是轻量版的synchronized,volatile不保证原子性,但是如果是对一个共享变量进行多个线程的赋值,而没有其他的操作,那么就可以用volatile来代替synchronized,因为赋值本身是有原子性的,而volatile又保证了可见性,所以就可以保证线程安全了。

    总结

    注:以上所有的内容如果能全部掌握我想Volatile在面试官那是很加分了,但是我还没讲到很多关于计算机内存那一块的底层,那大家就需要后面去补课了,如果等得及,也可以等到我写计算机基础章节。

    絮叨

    因为更新文章和视频,丙丙已经半年多的周末没休息了,都是在公司那个工位冲冲冲,一直想找时间出去玩,想着年假一天没用,就请了两天出去玩一下。

    这样五一就可以早点回来,准备恢复视频的更新,你在看的时候呢,敖丙应该在出游的列车上了,是的我就背了这个包,到写完的时候,我还没确定去哪里,提前祝大家节日愉快。

    我是敖丙,一个在互联网苟且偷生的工具人。

    你知道的越多,你不知道的越多人才们的 【三连】 就是丙丙创作的最大动力,我们下期见!

    注:如果本篇博客有任何错误和建议,欢迎人才们留言,你快说句话啊


    05-07 13:13