volatile变量

        上篇文章介绍了Java内存模型,没看过《深入理解Java虚拟机》的同学可以去看下Java内存模型

        Java内存模型对volatile专门定义了一些特殊的访问规则,假定T表示一个线程,V和W分别表示两个volatile变量,那么在进行read、load、use、assign、store、和write操作时需要满足如下规则

1)只有当线程T对变量V执行的前一个动作时load的时候,线程T才能对变量V执行use动作。并且只有线程T对变量V执行的后一个动作是use的时候,线程T才能对变量V执行load动作。线程T对变量V的use动作可以认为是和线程T对变量V的load、read动作相关联,必须连续一起出现(这条规则要求在工作内存中,每次使用V前都必须先从主内存刷新最新的值,用于保证能看见其他线程对变量V所做的修改后的值)

2)只有当线程T对变量V执行的前一个动作时assign的时候,线程T才能对变量V执行store动作,并且,只有当线程T对变量V执行的后一个动作是store的时候,线程T才能对变量V执行assign动作。线程T对变量V的assign动作可以认为是和线程T对变量V的store、wtite动作相关联,必须连续一起出现(这条规则要求在工作内存中,每次修改V后都必须立刻同步回主内存中,用于保证其他线程可以看见自己对变量V所做的修改)

3)假定动作A是线程T对变量V实施的use或assign动作,动作F是和动作A相关联的load或store动作,假定动作P是和动作F相对应的对变量V的read或write动作;类似的,假定动作B是线程T对变量W实施的use或assign动作,假定动作G是和动作B相关联的load或store动作,假定动作Q是和动作G相应的对变量W的read或write动作。如果A先于B,那么P先于Q(这条规则要求volatile修改的变量不会被指令重排序优化,保证代码的执行顺序与程序的顺序相同)

可以说volatile关键字是Java虚拟机提供的最轻量级的同步机制。

        当一个变量定义为volatile之后具备如下特性:

        1.可见性:指当一条线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的。普通变量的值在线程间传递均需通过主内存来完成,例:线程A修改了一个普通变量的值,然后向主内存进行回写,另外一条线程B在线程A回写完成了后再从主内存进行读取操作,新变量的值才会对线程B可见。

        虽然volatile型变量是线程可见的,对volatile变量所有的读写都能立刻反应到其他线程之中,但基于volatile变量的运算在并发下并不是安全的,因为Java里面的运算并不是原子操作。例:race ++,我们用javap反编译这句代码会发现在Class文件中是由4条字节码指令构成,(这里图1是书中原图,图2是笔者自己反编译的,可能由于Java虚拟机版本的问题2者不太一样,请知道的大佬告知,为文章严谨性看图1就可以了)

图1
图2

从字节码层面很容易分析出来,假如有两条线程同时执行这条语句,线程A执行getstatic指令把race的值取到操作栈顶时,volatile关键字保证来race的值在此时是正确的,但是执行iconst_1、iadd这些指令时线程B可能已经把race的值加大了,而在操作栈定的值就变成了过期的数据。

        由于volatile变量只能保证可见性,所以在不符合以下两条规则的运算场景中,我们仍然要通过加锁来保证原子性

        1)运算结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量的值

        2)变量不需要与其他的状态变量共同参与不变约束

2.禁止指令重排序优化,这里说明下,为了使处理器内部的运算单元能尽量被充分利用,处理器可能会对输入代码进行乱序执行优化。与之类似的Java虚拟机的即时编译器也有指令重排序优化。还不知道的同学可以去查下(说的就是我自己)。

        普通的变量仅仅会保证在该方法的执行过程中所有依赖值结果的地方都能获取到正确的结果,而不能保证变量赋值操作的顺序与程序代码中的执行顺序一致。这样理解起来还是有点抽象,笔者举个自己在书中看了茅塞顿开的例子

这里是一段汇编代码,方便起见就用书中原图了

这是段标准的DCL单例,变量用valatile修饰,赋值后(mov%eax,0x150(%esi)这句便是赋值操作)多执行了一个“lock addl & 0x0,(%esp)”操作,这个操作相当于一个内存屏障,只有一个cpu访问时并不需要内存屏障,但如果有两个或更多cpu访问同一块内存,且其中一个在观测另一个,就需要内存屏障来保证一致性了。这句指令“addl & 0x0,(%esp)”(把esp寄存器的值加0)显然是一个空操作,关键在于lock前缀,它的作用是使得本cpu的Cache写入了内存,该写入动作也会引起别的cpu或者别的内核无效化其Cache,这中操作箱单于对Cache中的变量做了一个“store和write”操作。所以通过这样一个空操作可以让前面valatile变量的修改对其他cpu立即可见。

        这段基本是书中原文,这样说可能有的同学不太懂(我就没懂),下面在结合具体代码说下,instance = new Singleton() 这句代码并不是一个原子操作,大致做了3件事情

1)给Singleton实例分配内存空间

2)初始化Singleton对象

3)将instance对象指向分配的内存空间

由于Java虚拟机指令重排序优化,使得2、3的顺序是无法保证的,如果出现了132的情况,并且在3执行完毕2未执行之前线程切换了,这个时候instance非空,所以直接返回instance,结果可想而知

    避免篇幅过长就到这吧

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

推荐阅读更多精彩内容

  • 第6章类文件结构 6.1 概述 6.2 无关性基石 6.3 Class类文件的结构 java虚拟机不和包括java...
    kennethan阅读 903评论 0 2
  • 转载自 IBM Java 理论与实践: 正确使用 Volatile 变量 你真的了解volatile关键字吗? v...
    LongHuang阅读 1,315评论 1 4
  • 昨天去考试,在考场上遇到之前的老师,上了岁数一老头一大早站在考场外,生怕学生临时有什么问题,他可以回答他们的问题。...
    许多的yolyol阅读 179评论 1 1
  • 十七岁的某一天,那年盛夏,那年心动,某月相识,某月回首,五日定情,二十二日绵长,许你安好。放荡不羁独爱自由,零碎不...
    淑媛媛阅读 216评论 1 2