Sal*_*ran 9 java assembly multithreading intel
我写了这个简单的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++;
}
}
Run Code Online (Sandbox Code Playgroud)
这为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)
Run Code Online (Sandbox Code Playgroud)
这是我对以下汇编代码的理解:
JMM声明在每次易失性读取之前必须有一个加载内存屏障,并且在每次易失性写入之后必须存在存储障碍.我的问题是:
因此,所有屏障StoreStore,LoadLoad,LoadStore都是x86上的no-op. StoreLoad除外,可以通过 mfence或cpuid或锁定insn实现.您已经可以使用汇编代码确认.其他障碍只是意味着限制编译器优化和转换,因此它们不会破坏java内存模型规范.
当你在intel处理器上运行时,我假设它的x86.
请阅读
http://psy-lob-saw.blogspot.com/2013/08/memory-barriers-are-not-free.html
Lock不是指令,而是指令前缀(表现为storeLoad屏障).
volatileJava中的关键字仅保证跳过线程本地副本和缓存,并且直接从主内存加载值或写入主内存。但它不包含锁定机制。因此,从 读取volatile或写入volatile是原子的,但是一系列读取和写入操作,如上面的
j++
不是原子的,因为其他一些线程可以修改j主内存中变量的读取和写入之间的值。要实现原子增量,您需要使用封装在 java 中的原子类中的 CAS 操作,例如AtomicInteger等。或者,如果您喜欢低级编程,您可以在Unsafe类 EgUnsafe.compareAndSwapInt等中使用原子方法。
| 归档时间: |
|
| 查看次数: |
975 次 |
| 最近记录: |