gpt4 book ai didi

java - 了解运行时无争用的同步方法

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:48:15 24 4
gpt4 key购买 nike

java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

这一切都是为了学习目的,而不是为了在生产中应用。

我试图了解 synchronized 在运行时在 JVM HotSpot 上的行为。这是我尝试过的:

public class App {
public static int i = 0;

public static void main(String[] args) {
for(int i = 0; i < 10000; i++){
increment();
}
if(new Object().hashCode() != i){
System.out.print("");
}
}

static synchronized void increment(){
i++;
}
}

这是整个应用程序。我有兴趣了解这将如何在运行时工作。所以我用 java -server -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*App.increment -jar target/test-1.0.0.jar 反汇编得到了这个:

  # {method} {0x00007f62e5693438} 'increment' '()V' in 'com/test/App'
# [sp+0x50] (sp of caller)
0x00007f62d1112880: mov %eax,0xfffffffffffec000(%rsp)
0x00007f62d1112887: push %rbp
0x00007f62d1112888: sub $0x40,%rsp
0x00007f62d111288c: movabs $0xd6f77a00,%rsi ; {oop(a 'java/lang/Class' = 'com/test/App')}
0x00007f62d1112896: lea 0x20(%rsp),%rdi
0x00007f62d111289b: mov %rsi,0x8(%rdi)
0x00007f62d111289f: mov (%rsi),%rax
0x00007f62d11128a2: mov %rax,%rbx
0x00007f62d11128a5: and $0x7,%rbx
0x00007f62d11128a9: cmp $0x5,%rbx
0x00007f62d11128ad: jne 0x7f62d1112934
0x00007f62d11128b3: mov 0x8(%rsi),%ebx
0x00007f62d11128b6: shl $0x3,%rbx
0x00007f62d11128ba: mov 0xa8(%rbx),%rbx
0x00007f62d11128c1: or %r15,%rbx
0x00007f62d11128c4: xor %rax,%rbx
0x00007f62d11128c7: and $0xffffffffffffff87,%rbx
0x00007f62d11128cb: je 0x7f62d111295c
0x00007f62d11128d1: test $0x7,%rbx
0x00007f62d11128d8: jne 0x7f62d1112921
0x00007f62d11128da: test $0x300,%rbx
0x00007f62d11128e1: jne 0x7f62d1112900
0x00007f62d11128e3: and $0x37f,%rax
0x00007f62d11128ea: mov %rax,%rbx
0x00007f62d11128ed: or %r15,%rbx
0x00007f62d11128f0: lock cmpxchg %rbx,(%rsi)
0x00007f62d11128f5: jne 0x7f62d11129dd
0x00007f62d11128fb: jmpq 0x7f62d111295c
0x00007f62d1112900: mov 0x8(%rsi),%ebx
0x00007f62d1112903: shl $0x3,%rbx
0x00007f62d1112907: mov 0xa8(%rbx),%rbx
0x00007f62d111290e: or %r15,%rbx
0x00007f62d1112911: lock cmpxchg %rbx,(%rsi)
0x00007f62d1112916: jne 0x7f62d11129dd
0x00007f62d111291c: jmpq 0x7f62d111295c
0x00007f62d1112921: mov 0x8(%rsi),%ebx
0x00007f62d1112924: shl $0x3,%rbx
0x00007f62d1112928: mov 0xa8(%rbx),%rbx
0x00007f62d111292f: lock cmpxchg %rbx,(%rsi)
0x00007f62d1112934: mov (%rsi),%rax
0x00007f62d1112937: or $0x1,%rax
0x00007f62d111293b: mov %rax,(%rdi)
0x00007f62d111293e: lock cmpxchg %rdi,(%rsi)
0x00007f62d1112943: je 0x7f62d111295c
0x00007f62d1112949: sub %rsp,%rax
0x00007f62d111294c: and $0xfffffffffffff007,%rax
0x00007f62d1112953: mov %rax,(%rdi)
0x00007f62d1112956: jne 0x7f62d11129dd
0x00007f62d111295c: movabs $0x7f62e5693668,%rax ; {metadata(method data for {method} {0x00007f62e5693438} 'increment' '()V' in 'com/test/App')}
0x00007f62d1112966: mov 0xdc(%rax),%esi
0x00007f62d111296c: add $0x8,%esi
0x00007f62d111296f: mov %esi,0xdc(%rax)
0x00007f62d1112975: movabs $0x7f62e5693438,%rax ; {metadata({method} {0x00007f62e5693438} 'increment' '()V' in 'com/test/App')}
0x00007f62d111297f: and $0x1ff8,%esi
0x00007f62d1112985: cmp $0x0,%esi
0x00007f62d1112988: je 0x7f62d11129f0
0x00007f62d111298e: movabs $0xd6f77a00,%rax ; {oop(a 'java/lang/Class' = 'com/test/App')}
0x00007f62d1112998: mov 0x68(%rax),%esi ;*getstatic i
; - com.test.App::increment@0 (line 19)

0x00007f62d111299b: incl %esi
0x00007f62d111299d: mov %esi,0x68(%rax) ;*putstatic i
; - com.test.App::increment@5 (line 19)

0x00007f62d11129a0: lea 0x20(%rsp),%rax
0x00007f62d11129a5: mov 0x8(%rax),%rdi
0x00007f62d11129a9: mov (%rdi),%rsi
0x00007f62d11129ac: and $0x7,%rsi
0x00007f62d11129b0: cmp $0x5,%rsi
0x00007f62d11129b4: je 0x7f62d11129d1
0x00007f62d11129ba: mov (%rax),%rsi
0x00007f62d11129bd: test %rsi,%rsi
0x00007f62d11129c0: je 0x7f62d11129d1
0x00007f62d11129c6: lock cmpxchg %rsi,(%rdi)
0x00007f62d11129cb: jne 0x7f62d1112a04 ;*return
; - com.test.App::increment@8 (line 20)

0x00007f62d11129d1: add $0x40,%rsp
0x00007f62d11129d5: pop %rbp
0x00007f62d11129d6: test %eax,0x18b4c724(%rip) ; {poll_return}
0x00007f62d11129dc: retq
0x00007f62d11129dd: mov %rsi,0x8(%rsp)
0x00007f62d11129e2: mov %rdi,(%rsp)
0x00007f62d11129e6: callq 0x7f62d1105420 ; OopMap{rsi=Oop [40]=Oop off=363}
;*synchronization entry
; - com.test.App::increment@-1 (line 19)
; {runtime_call}
0x00007f62d11129eb: jmpq 0x7f62d111295c
0x00007f62d11129f0: mov %rax,0x8(%rsp)
0x00007f62d11129f5: movq $0xffffffffffffffff,(%rsp)
0x00007f62d11129fd: callq 0x7f62d1106fa0 ; OopMap{[40]=Oop off=386}
;*synchronization entry
; - com.test.App::increment@-1 (line 19)
; {runtime_call}
0x00007f62d1112a02: jmp 0x7f62d111298e
0x00007f62d1112a04: lea 0x20(%rsp),%rax
0x00007f62d1112a09: mov %rax,(%rsp)
0x00007f62d1112a0d: callq 0x7f62d11057e0 ; {runtime_call}
0x00007f62d1112a12: jmp 0x7f62d11129d1
0x00007f62d1112a14: nop
0x00007f62d1112a15: nop
0x00007f62d1112a16: mov 0x2a8(%r15),%rax
0x00007f62d1112a1d: movabs $0x0,%r10
0x00007f62d1112a27: mov %r10,0x2a8(%r15)
0x00007f62d1112a2e: movabs $0x0,%r10
0x00007f62d1112a38: mov %r10,0x2b0(%r15)
0x00007f62d1112a3f: mov %rax,%rbx
0x00007f62d1112a42: lea 0x20(%rsp),%rax
0x00007f62d1112a47: mov 0x8(%rax),%rsi
0x00007f62d1112a4b: mov (%rsi),%rdi
0x00007f62d1112a4e: and $0x7,%rdi
0x00007f62d1112a52: cmp $0x5,%rdi
0x00007f62d1112a56: je 0x7f62d1112a73
0x00007f62d1112a5c: mov (%rax),%rdi
0x00007f62d1112a5f: test %rdi,%rdi
0x00007f62d1112a62: je 0x7f62d1112a73
0x00007f62d1112a68: lock cmpxchg %rdi,(%rsi)
0x00007f62d1112a6d: jne 0x7f62d1112a80
0x00007f62d1112a73: mov %rbx,%rax
0x00007f62d1112a76: add $0x40,%rsp
0x00007f62d1112a7a: pop %rbp
0x00007f62d1112a7b: jmpq 0x7f62d10755a0 ; {runtime_call}
0x00007f62d1112a80: lea 0x20(%rsp),%rax
0x00007f62d1112a85: mov %rax,(%rsp)
0x00007f62d1112a89: callq 0x7f62d11057e0 ; {runtime_call}
0x00007f62d1112a8e: jmp 0x7f62d1112a73
0x00007f62d1112a90: hlt
0x00007f62d1112a91: hlt
0x00007f62d1112a92: hlt
0x00007f62d1112a93: hlt
0x00007f62d1112a94: hlt
0x00007f62d1112a95: hlt
0x00007f62d1112a96: hlt
0x00007f62d1112a97: hlt
0x00007f62d1112a98: hlt
0x00007f62d1112a99: hlt
0x00007f62d1112a9a: hlt
0x00007f62d1112a9b: hlt
0x00007f62d1112a9c: hlt
0x00007f62d1112a9d: hlt
0x00007f62d1112a9e: hlt
0x00007f62d1112a9f: hlt

让我感到困惑的是这个片段:

  0x00007f62d11128f0: lock cmpxchg %rbx,(%rsi)   ;1st cmpxchg
0x00007f62d11128f5: jne 0x7f62d11129dd
0x00007f62d11128fb: jmpq 0x7f62d111295c
0x00007f62d1112900: mov 0x8(%rsi),%ebx
0x00007f62d1112903: shl $0x3,%rbx
0x00007f62d1112907: mov 0xa8(%rbx),%rbx
0x00007f62d111290e: or %r15,%rbx
0x00007f62d1112911: lock cmpxchg %rbx,(%rsi) ;2nd cmpxchg
0x00007f62d1112916: jne 0x7f62d11129dd
0x00007f62d111291c: jmpq 0x7f62d111295c
0x00007f62d1112921: mov 0x8(%rsi),%ebx
0x00007f62d1112924: shl $0x3,%rbx
0x00007f62d1112928: mov 0xa8(%rbx),%rbx
0x00007f62d111292f: lock cmpxchg %rbx,(%rsi) ;3rd cmpxchg
0x00007f62d1112934: mov (%rsi),%rax
0x00007f62d1112937: or $0x1,%rax
0x00007f62d111293b: mov %rax,(%rdi)
0x00007f62d111293e: lock cmpxchg %rdi,(%rsi) ;4th cmpxchg
0x00007f62d1112943: je 0x7f62d111295c
0x00007f62d1112949: sub %rsp,%rax
0x00007f62d111294c: and $0xfffffffffffff007,%rax
0x00007f62d1112953: mov %rax,(%rdi)
0x00007f62d1112956: jne 0x7f62d11129dd

首先我们比较和交换rbx[rsi]。由于 lock cmpxchng 修改了 ZF,我们有条件地跳转到 jne 0x7f62d11129dd(我认为这是在 CAS 失败的情况下)。如果 CAS 成功,我们将无条件跳转到 jmpq 0x7f62d111295c

问题:

为什么我们有 4 个 lock cmpxchg %rbx, ($rsi) 如果我们在第一个 lock cmpxchg %rbx, ($rsi) 之后的跳跃中跳过它们>?

UPD:我想我理解为什么我们需要这种跳跃。没有先注意到这些说明:

0x00007f62d11128d1: test    $0x7,%rbx
0x00007f62d11128d8: jne 0x7f62d1112921
0x00007f62d11128da: test $0x300,%rbx
0x00007f62d11128e1: jne 0x7f62d1112900

目前还不太清楚的是rbx当时包含的内容。我看了一开始。在这里:

0x00007f62d111288c: movabs  $0xd6f77a00,%rsi  ; seems the object data
;...
0x00007f62d111289b: mov %rsi,0x8(%rdi) ; Header offset?
0x00007f62d111289f: mov (%rsi),%rax
0x00007f62d11128a2: mov %rax,%rbx
0x00007f62d11128a5: and $0x7,%rbx ; Why do we do this and?

最佳答案

  1. 您正在查看 C1 编译的方法。这不是通常在热路径上运行的。一旦 main 方法用 C2 编译,就不会调用 increment 方法,而是内联到外部循环中。
  2. 您要询问的这段代码是偏向锁定输入 序列。为了更好地理解它,您需要知道如何 Biased Locking works . rbx 这里包含了对象头(mark word)。 和 $0x7, rbx 指令屏蔽偏向锁模式位。
  3. 查看MacroAssembler::biased_locking_enter的源代码看看发生了什么。顺便说一句,这些来源附有许多真正有助于理解算法的宝贵评论。

关于java - 了解运行时无争用的同步方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48475922/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com