Why reading a volatile and writing to a field member is not scalable in Java?

前端 未结 5 464
遇见更好的自我
遇见更好的自我 2021-01-30 22:04

Observe the following program written in Java (complete runnable version follows, but the important part of the program is in the snippet a little bit further below):

         


        
5条回答
  •  猫巷女王i
    2021-01-30 22:14

    This is what I think is happening (keep in mind I'm not familiar with HotSpot):

    0xf36c9fd0: mov    0x6c(%ecx),%ebp    ; vfoo
    0xf36c9fd3: test   %ebp,%ebp          ; vfoo is null?
    0xf36c9fd5: je     0xf36c9ff7         ;   throw NullPointerException (I guess)
    0xf36c9fd7: movl   $0x1,0x8(%ebp)     ; vfoo.x = 1
    0xf36c9fde: mov    0x68(%ecx),%ebp    ; sz
    0xf36c9fe1: inc    %ebx               ; i++
    0xf36c9fe2: test   %edi,0xf7725000    ; safepoint on end of loop
    0xf36c9fe8: cmp    %ebp,%ebx          ; i < sz?
    0xf36c9fea: jl     0xf36c9fd0
    
    
    0xf3771ad0: mov    0x6c(%ecx),%ebp          ; vfoo
    0xf3771ad3: test   %ebp,%ebp                ; vfoo is null?
    0xf3771ad5: je     0xf3771b09               ;   throw NullPointerException (I guess)
    0xf3771ad7: movl   $0x1,0x8(%ebp)           ; vfoo.x = 1
    0xf3771ade: mov    0x6c(%ecx),%ebp          ; \
    0xf3771ae1: mov    %ebp,0x70(%ecx)          ; / bar = vfoo
    0xf3771ae4: mov    0x68(%ecx),%edi          ; sz
    0xf3771ae7: inc    %ebx                     ; i++
    0xf3771ae8: mov    %ecx,%eax                ; 
    0xf3771aea: shr    $0x9,%eax                ; ??? \ Probably replaced later
    0xf3771aed: movb   $0x0,-0x3113c300(%eax)   ; ??? / by some barrier code?
    0xf3771af4: test   %edi,0xf77ce000          ; safepoint
    0xf3771afa: cmp    %edi,%ebx                ; i < sz ?
    0xf3771afc: jl     0xf3771ad0               ;
    

    The reason I think the above code stands in for a barrier is that when taking the NullPointerException, the scalable version has a XCHG, which acts as a barrier, while the non-scalable version has a NOP there.

    The rationale would be that there needs to be a happens-before ordering between the initial load of vfoo and joining the thread. In the volatile case, the barrier would be inside the loop, so it wouldn't need to be elsewhere. What I don't understand is why XCHG isn't used inside the loop. Maybe runtime detection of MFENCE support?

提交回复
热议问题