我写了这个简单的Java程序:

package com.salil.threads;

public class IncrementClass {

    static volatile int j = 0;
    static int i = 0;

    public static void main(String args[]) {

        for(int a=0;a<1000000;a++);
        i++;
        j++;
    }
}

这将为i ++和j ++生成以下反汇编代码(除去了剩余的反汇编代码):
  0x0000000002961a6c: 49ba98e8d0d507000000 mov       r10,7d5d0e898h
                                                ;   {oop(a 'java/lang/Class' = 'com/salil/threads/IncrementClass')}
  0x0000000002961a76: 41ff4274            inc       dword ptr [r10+74h]
                                                ;*if_icmpge
                                                ; - com.salil.threads.IncrementClass::main@5 (line 10)
  0x0000000002961a7a: 458b5a70            mov       r11d,dword ptr [r10+70h]
  0x0000000002961a7e: 41ffc3              inc       r11d
  0x0000000002961a81: 45895a70            mov       dword ptr [r10+70h],r11d
  0x0000000002961a85: f083042400          lock add  dword ptr [rsp],0h
                                                ;*putstatic j
                                                ; - com.salil.threads.IncrementClass::main@27 (line 14)

这是我对以下汇编代码的了解:
  • mov r10,7d5d0e898h:将指针移至IncrementClass.class以注册r10
  • inc dword ptr [r10 + 74h]:将[r10 + 74h]地址处的4字节值递增,即(i。)
  • mov r11d,dword ptr [r10 + 70h]:将地址[r10 + 70h]上的4值值移动到寄存器r11d(即,将j的值移动到r11d)
  • inc r11d:递增r11d
  • mov dword ptr [r10 + 70h],r11d:将r11d的值写入[r10 + 70h],以便其他线程可以看到
    -lock add dword ptr [rsp],0h:锁定由堆栈指针rsp表示的内存地址,并向其添加0。

  • JMM指出,在每个易失性读取之前必须有一个加载内存屏障,而在每个易失性写入之后都必须有一个存储屏障。我的问题是:
  • 为什么在将j读入r11d之前没有负载障碍?
  • 锁和加到rsp如何确保r11d中的j值传播回主内存。我从intel规范中了解到的是,在操作期间,锁为cpu提供了对指定内存地址的排他锁。
  • 最佳答案

    英特尔处理器x86带有strong memory model

    因此,所有的屏障StoreStore,LoadLoad和LoadStore在x86上都不可用。
    除StoreLoad外,可以通过 mfence或cpuid或锁定insn 实现。
    您已经可以使用汇编代码进行确认。其他障碍仅意味着限制编译器的优化和转换,以免破坏java memory model spec

    当您在英特尔处理器上运行时,我假设它是x86。

    请阅读

  • http://gee.cs.oswego.edu/dl/jmm/cookbook.html供参考。
  • http://psy-lob-saw.blogspot.com/2013/08/memory-barriers-are-not-free.html
  • http://jsr166-concurrency.10961.n7.nabble.com/x86-NOOP-memory-barriers-td9991.html

  • 锁不是指令,而是指令的前缀(表现为storeLoad屏障)。
  • What does the "lock" instruction mean in x86 assembly?
  • Why we need lock prefix before CMPXCHG
  • 07-24 13:45