volatile

深入来说:通过加入内存屏障和禁止重排序优化来实现的

对volatile变量执行写操作时,会在写操作后加入一条store屏障指令.
对volatile变量执行读操作时,会在读操作前加入一条load屏障指令.

通俗地讲:volatile变量在每次被线程访问时,都强迫从主内存中重读该变量的值,
而当该变量发生变化时,又会强迫线程将最新的值刷新到主内存,
这样任何时刻,不同的线程总能看到该变量的最新值。
复制代码
线程写volatile变量的过程:

改变线程工作内存中volatile变量副本的值
将改变后的副本的值从工作内存刷新到主内存

线程读volatile变量的过程:

从主内存中读取volatile变量的最新值到线程的工作内存中
从工作内存中读取volatile变量的副本

volatile:从最终汇编语言从面来看,volatile使得每次将i进行了修改之后,增加了一个内存屏障lock addl $0x0,(%rsp)保证修改的值必须刷新到主内存才能进行内存屏障后续的指令操作。但是内存屏障之前的指令并不是原子的代码例子 public static volatile int race = 0; public static void increase() { race++; }字节码:public static void increase(); Code: 0: getstatic #2 // Field race:I 3: iconst_1 4: iadd 5: putstatic #2 // Field race:I 8: return指令“lock; addl $0,0(%%esp)”表示加锁,把0加到栈顶的内存单元,该指令操作本身无意义,但这些指令起到内存屏障的作用,让前面的指令执行完成。具有XMM2特征的CPU已有内存屏障指令,就直接使用该指令volatile方式的i++,总共是四个步骤:i++实际为load、Increment、store、Memory Barriers 四个操作。内存屏障是线程安全的,但是内存屏障之前的指令并不是.在某一时刻线程1将i的值load取出来,放置到cpu缓存中,然后再将此值放置到寄存器A中,然后A中的值自增1(寄存器A中保存的是中间值,没有直接修改i,因此其他线程并不会获取到这个自增1的值)。如果在此时线程2也执行同样的操作,获取值i10,自增1变为11,然后马上刷入主内存。此时由于线程2修改了i的值,实时的线程1中的i10的值缓存失效,重新从主内存中读取,变为11。接下来线程1恢复。将自增过后的A寄存器值11赋值给cpu缓存i。这样就出现了线程安全问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值