java volatile关键字

volatile实现细节:
字节码层面:
  • 字段的访问标志增加了一个0x0040 [volatile]
JVM层面:前后都会加屏障,不能互换
  • StoreStoreBarrier
  • volatile 写操作
  • StoreLoadBarrier

  • LoadLoadBarrier
  • volatile读操作
  • LoadStoreBarrier
hotspot的实现

偷懒了,并没有根据不同的CPU做优化,而是使用的所有CPU都通用的lock指令

bytecodeinterpreter.cpp

int field_offset = cache->f2_as_index();
if (cache->is_volatile()) {
    if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
        OrderAccess::fence();
    }

    orderaccess_linux_x86.inline.hpp
        inline void OrderAccess::fence() {
        if (os::is_MP()) {
            // always use locked addl since mfence is sometimes expensive
            #ifdef AMD64
            __asm__ volatile ("lock; addl $0,0(%%rsp)" : : : "cc", "memory");
            #else
            __asm__ volatile ("lock; addl $0,0(%%esp)" : : : "cc", "memory");
            #endif
        }
    }
  • lock用于在多处理器中执行指令时对共享内存的独占使用,它的作用是能将当前处理器对应缓存的内容刷新到内存,并使其他处理器对应的缓存失效,另外还提供了有序的指令无法越过这个内存屏障的作用。
  • lock; addl $0,0(%%esp)相当于一个内存屏障(Memory Barrier,指重排序时不能把后面的指令重排序到内存屏障之前的位置),只有一个cpu核访问内存时,并不需要内存屏障,但如果有两个或者更多CPU核访问同一块内存,且其中有一个在观测另一个,就需要内存屏障来保证一致性,addl $0,0(%%esp)是一条空操作,可以让前面的volatile变量的修改对其他CPU立即可见。
volatile并不能保证原子性

在volatile修改之后,增加了一个内存屏障lock; addl $0,0(%%esp),内存屏障之前并不是原子的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值