JAVA中volatile介绍

Volatile有序性

在并发编程中谈及到的无非是可见性、有序性及原子性。而这里的Volatile只能够保证前两个性质,对于原子性还是不能保证的,只能通过锁的形式帮助他去解决原子性操作。

package com.montos.detail;
public class Singleton {
    public static volatile Singleton instance = null;
    private Singleton() {
    }
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (instance) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

上面的代码是利用了单例模式里面的一个双重校验的写法,里面的实例变量中就是加上了volatile关键字,可能大家对于加不加这个关键字没啥感觉,因为去除这个关键字就可以保证多线程的情况下,外部能够拿到唯一的对象,还需要加上这个关键字干什么?。

双重校验的写法:第一次判断是否为null是为了拒绝掉当对象不为空的时候剩余的线程。里面加锁是为了当对象为null的时候,此时同时进来两个线程(A和B两个线程),我们要保证只有一个线程才可以初始化对象,所以在这里面加上了锁,这样A拿到了锁进去初始化对象,然后进行返回,B再进去此时发现不为null,那么就不执行初始化的过程。这样就能保证上面的单例模式的正常运行,同时为系统也是节约了许多开销(避免每个线程进来加锁--懒汉式写法等。。)

在理解上面的为什么不安全的情况下,我们首先要理解对象实例化的步骤:

  1. 分配内存空间。
  2. 初始化对象。
  3. 将内存空间的地址赋值给对应的引用。

上面是正常情况下,对象实例化的步骤,但是由于操作系统方面的原因。上面的第二步可能与第三步进行对换,如果发生这种情况,那么此时拿到的对象也只是一个引用,对于后面的业务操作可能存在错误的发生。

序号 指令 说明
1 IF 取值
2 ID 译码和取寄存器操作数
3 EX 执行或者有效地址计算
4 MEM 存储器访问
5 WB 写回

未进行指令重排的Demo:
a = b + c; d = e -f ;

从上图可以看到有几个打x的地方,如果按照顺序执行的话,CPU是需要一个时钟周期来等待的,首先看第一个红色框的,第一个需要空出一个时钟周期是因为当前变量C还没有写入,此时是不可以进行两个值计算的,我们需要等待变量C的写入才可以进行执行两个数的求和,第二个空的时钟周期是因为当前一个时钟周期内,一个物理逻辑单位只能被一个指令执行,如果不空出一个时钟周期,那么就会与上面的EX起到冲突,第三个空档也是一样的道理。第二个红色框也是如此。

这上面就是如果计算机不进行指令重排的话,一个简单的计算,我们就可能浪费了5个时钟周期,即一条指令的从头到尾执行,所以计算机为了高效,就会对原来的指令进行重排,让CPU的资源能够得到很好的使用。

我们就将变量e的指令执行放在变量c之后,变量f的指令执行放在计算第一个表达式指令之后:

结果我们看到:

这个时候我们发现并没有浪费一个时钟周期,程序也达到了想要的计算效果,这就是计算机对于指令重排的一个优点,使得流水线更加的顺畅。

上面就说明了指令重排有时候对于程序执行是好的,但是有些情况下我们并不想发生这种情况,就是对象实例化的时候,我们就希望它能够按照顺序执行的方式执行下去。这个时候volatile就帮助了我们,它能够有效的防止指令重排。

Volatile有序性原理

volatile之所以能够阻止指令重排,是因为底层JVM里面利用了内存屏障来实现的,内存屏障主要有三点功能:

  1. 它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;
  2. 它会强制将对缓存的修改操作立即写入主存;
  3. 如果是写操作,它会导致其他CPU中对应的缓存行无效。

这里主要有四种类型的屏障操作:

(1)LoadLoad 屏障
执行顺序:Load1—>Loadload—>Load2
确保Load2及后续Load指令加载数据之前能访问到Load1加载的数据。

(2)StoreStore 屏障
执行顺序:Store1—>StoreStore—>Store2
确保Store2以及后续Store指令执行前,Store1操作的数据对其它处理器可见。

(3)LoadStore 屏障
执行顺序: Load1—>LoadStore—>Store2
确保Store2和后续Store指令执行前,可以访问到Load1加载的数据。

(4)StoreLoad 屏障
执行顺序: Store1—> StoreLoad—>Load2
确保Load2和后续的Load指令读取之前,Store1的数据对其他处理器是可见的。

通过上面内存屏障的限制,我们使用volatile就可以保证指令不会被操作系统进行重排。

Volatile可见性

线程本身并不直接与主内存进行数据的交互,而是通过线程的工作内存来完成相应的操作。这也是导致线程间数据不可见的本质原因。因此要实现volatile变量的可见性,直接从这方面入手即可。对volatile变量的写操作与普通变量的主要区别有两点:

  1. 修改volatile变量时会强制将修改后的值刷新的主内存中。

  2. 修改volatile变量后会导致其他线程工作内存中对应的变量值失效。因此,再读取该变量值的时候就需要重新从读取主内存中的值。

通过这两点就可以很好的解决可见性问题。

写在最后

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,706评论 4 366
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,002评论 1 301
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,462评论 0 250
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,375评论 0 216
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,763评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,849评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,033评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,768评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,490评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,734评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,204评论 1 264
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,566评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,227评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,137评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,934评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,926评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,774评论 2 274

推荐阅读更多精彩内容