Concurrent actual combat--analysis of atomic class atomicreference and bottom source Compareandswapobject __java

Source: Internet
Author: User
Tags cas volatile

This article: Analysis of atomic class Atomicreference analysis source

In Atomicreference

Public Final Boolean Compareandset (v expect, v update) {return
        unsafe.compareandswapobject (this, Valueoffset, expect, update);
    }
Public final V Getandset (v newvalue) {return
        (v) unsafe.getandsetobject (this, valueoffset, newvalue);


    Public final Object Getandsetobject (object var1, Long var2, object VAR4) {
        object var5;
        do {
            VAR5 = This.getobjectvolatile (var1, var2);} while (!this.compareandswapobject (var1, var2, Var5
        , VAR4))

        ; return VAR5;
    }

Analysis of Compareandswapobject Source code

Public Final Native Boolean Compareandswapobject (object var1, Long var2, Object Var4, Object VAR5);

You can see that the native method is declared, meaning that the method is implemented using a lower level of code (CPP) and needs to download the OPENJDK source to see it. The following is a brief introduction to the search source process.

After downloading good OPENJDK source code, import it into Idea's lib in this project, easy to find globally.

Refer to the native implementation rules to guess the CPP header files generated by the Javah tool.

Unsafe_entry (Jboolean, Unsafe_compareandswapobject (jnienv *env, Jobject UNSAFE, jobject obj, jlong offset, Jobject E_h, J Object x_h))
  unsafewrapper ("Unsafe_compareandswapobject");
  OOP x = Jnihandles::resolve (x_h); New value
  oop e = Jnihandles::resolve (e_h);//Expected value
  oop p = jnihandles::resolve (obj);
  heapword* addr = (Heapword *) Index_oop_from_field_offset_long (P, offset);//In memory specific location
  OOP res = Oopdesc::atomic_ Compare_exchange_oop (x, addr, E, true);//Another method was called
  Jboolean success  = (res = = e);  If the returned res equals E, the compare condition is determined (stating that the res should be the current value in memory), but there is actually an ABA problem
  if (success)//success is true, Indicates that the success has been exchanged at this time (called the lowest cmpxchg instruction)
    Update_barrier_set ((void*) addr, x);///Every time reference type data writes, a write is generated Barrier temporarily interrupt operation, with garbage collector return
  success;
Unsafe_end

Our direct global search (search scope is OPENJDK) This called method, you can see the definition and implementation of the method

Defined:
In the Opp.hpp file

  Static OOP Atomic_compare_exchange_oop (OOP exchange_value,
                                         volatile Heapword *dest,
                                         oop compare_value,
                                         BOOL Prebarrier = false);

Realize:
In the OPP.INLINE.HPP
(http://blog.csdn.net/lqp276/article/details/52231261 pointer compression related)

Inline OOP oopdesc::atomic_compare_exchange_oop (OOP exchange_value, Volati
                                                Le Heapword *dest, oop compare_value,  BOOL Prebarrier) {if (usecompressedoops) {//If compression common object pointer (compressedoops) is used, there is a process of renumbering if (Prebarrier)
    {Update_barrier_set_pre ((narrowoop*) dest, exchange_value); }//encode Exchange and compare value from OOP to T narrowoop val = encode_heap_oop (Exchange_value); The new value Narrowoop cmp = Encode_heap_oop (compare_value); Expected value Narrowoop old = (Narrowoop) Atomic::cmpxchg (Val, (narrowoop*) dest, CMP);
  The method invoked here is at the end of the article because it is compressed to 32 bits, so it can be operated with INT//decode old from T to OOP return Decode_heap_oop (old);
    else {if (prebarrier) {update_barrier_set_pre (oop*) dest, exchange_value); Return (OOP) atomic::cmpxchg_ptr (Exchange_value, (oop*) dest, compare_value); You can see this continues to invoke the other methods}}

Actions for 64-bit addresses

Inline Jlong    atomic::cmpxchg    (jlong    exchange_value, volatile jlong* dest    , Jlong compare_value    ) {
  int MP = OS::IS_MP ();
  Jint Ex_lo  = (jint) exchange_value;
  Jint Ex_hi  = * ((jint*) &exchange_value) + 1);
  Jint Cmp_lo = (jint) compare_value;
  Jint Cmp_hi = * ((jint*) &compare_value) + 1);
  __asm {
    push ebx
    push EDI
    mov eax, cmp_lo
    mov edx, cmp_hi
    mov edi, dest
    mov ebx, ex_lo
  
   mov ecx, Ex_hi
    lock_if_mp (MP)
    cmpxchg8b qword ptr [edi]
    pop edi
    pop ebx
  }
}
  

/**
cmpxchg8b-Compare and swap 8 bytes
Description
Compares 64-bit values and operands (target operands) in Edx:eax. If the two values are equal, the 64-bit value in the ECX:EBX is stored to the target operand. Otherwise, the value of the target operand is loaded into the edx:eax. The target operand is a 8-byte memory location. For a pair of edx:eax and ECX:EBX registers, EDX and ECX contain 64-bit values of 32 highs, EAX and EBX contain 32 lows.
This instruction can be used with the LOCK prefix, at which point the instruction is executed atomically. To simplify the processor's bus interface, the target operand can receive a write cycle regardless of the comparison result. If the comparison fails, the target operand is written back, otherwise the source operand is written to the target. (The processor never produces only lock reads but no lock writes).
* * Compareandswapint

To see a basic type of CAS source code

Unsafe_entry (Jboolean, Unsafe_compareandswapint (jnienv *env, Jobject UNSAFE, jobject obj, jlong offset, jint E, Jint x)) 
  unsafewrapper ("Unsafe_compareandswapint");
  OOP p = jnihandles::resolve (obj);
  jint* addr = (Jint *) Index_oop_from_field_offset_long (P, offset);
  Return (Jint) (Atomic::cmpxchg (x, addr, e)) = = e; This is where the CPU instructions above are called Cmpxchg
unsafe_end

In ATOMIC_WINDOWS_X86.INLINE.HPP:
MP represents multiprocessor, or multiprocessor. Finally, it transforms the assembly instruction according to the specific processor architecture to implement the CAs.
You need to precede the lock instruction when multiprocessor.

Inline Jint     atomic::cmpxchg    (jint     exchange_value, volatile jint* dest     , Jint compare_value     ) {
  //Alternative for interlockedcompareexchange
  int MP = OS::IS_MP ();
  __asm {
    mov edx, dest  //Eax,ecx,edx are 32-bit registers
    mov ecx, exchange_value
    mov eax, compare_value
    LOCK_IF_MP (MP)
    cmpxchg dword ptr [edx], ecx
  }
}

The above is the CPU level of CAs, described below:

Compares the value in the "AL, AX, or EAX register (depending on the size of the" operand) with the "the" "The" "the" on operand). If the two values are equal, the second operand (source operand) is loaded into the destination operand. Otherwise, the destination operand is loaded into the AL, AX, or EAX register. (If the expectation equals the value of the object address store, replace the value of the object address store with the new value, or change the expectation to the current Like the value of the address store)

This instruction can is used with a LOCK prefix to allow instruction. To simplify the interface to the processor's bus, the destination operand receives a write cycle without regard to the Res Ult of the comparison. The destination operand is written back if the comparison fails; Otherwise, the source operand is written into the destination. (The processor never produces a locked read without also a producing write.)

CAS is the basis for the atomicity of all atomic variables, and why a seemingly unnatural operation is so important. The reason for this is that the native operation will eventually evolve into a CPU instruction CMPXCHG, rather than multiple CPU instructions. Since CAS is only a directive, it is not interrupted by multithreaded scheduling, so it is possible to ensure that CAS operations are atomic. To add, many contemporary CPU types support CMPXCHG operations, but not all CPUs are supported, and for unsupported CPUs, locks are automatically added to ensure that their operations are not interrupted.
As a result, atomic variables provide atomicity from CAS operations, CAs are from unsafe, and are then guaranteed by the CPU's CMPXCHG directives.

(The following should be for the byte data of CAs, but the specific operation is somewhat strange, mainly the assignment of that piece)

You can also look for functions in a different way without using global search.
First look at the files that appear in the #inclued file.
Find the following (because the previously called method is also atomic)

#include "runtime/atomic.inline.hpp"

Then enter the HPP file and find

#include "runtime/atomic.hpp"

This time we'll go directly to the Atomic.cpp file.
(What exactly is the jint that http://blog.csdn.net/lxf310/article/details/39719445→ appears)

jbyte atomic::cmpxchg (jbyte exchange_value, volatile jbyte* dest, Jbyte compare_value) {Asser
  T (sizeof (jbyte) = = 1, "assumption.");
  uintptr_t dest_addr = (uintptr_t) dest;
  uintptr_t offset = dest_addr% sizeof (jint);
  Volatile jint* Dest_int = (volatile jint*) (Dest_addr-offset); Jint cur = *dest_int; Current value jbyte* cur_as_bytes = (jbyte*) (&cur);
  Cur's address jint new_val = cur; jbyte* new_val_as_bytes = (jbyte*) (&new_val); New_val's address//writes the new value first on the New_val address (because the last value is also taken from the jbyte* dest address).
  ) New_val_as_bytes[offset] = Exchange_value; The current value and expected values are compared, and the assumption is not satisfied, directly return Cur_as_bytes[offset], because unlike the Compare_value value, the upper method will determine the Exchange failure while (cur_as_bytes[offset] = =

    Compare_value) {//attempt to exchange, invoke machine instruction, return the value of the current address jint res = CMPXCHG (new_val, dest_int, cur);
    if (res = = cur) break;
    Otherwise, modify cur cur = res;
    New_val = cur;
  New_val_as_bytes[offset] = Exchange_value;
return Cur_as_bytes[offset]; }

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.