Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CAS #59

Open
boojongmin opened this issue Aug 7, 2023 · 0 comments
Open

CAS #59

boojongmin opened this issue Aug 7, 2023 · 0 comments

Comments

@boojongmin
Copy link
Owner

boojongmin commented Aug 7, 2023

public class Main {
    public static void main(String[] args) throws InterruptedException {
        var atomInt = new AtomicInteger(1);
        var r = atomInt.addAndGet(1);
        System.out.println(r);
    }
}
public class AtomicInteger extends Number implements java.io.Serializable {
    private static final long serialVersionUID = 6214790243416807050L;

    /*
     * This class intended to be implemented using VarHandles, but there
     * are unresolved cyclic startup dependencies.
     */
    private static final Unsafe U = Unsafe.getUnsafe();
    private static final long VALUE
        = U.objectFieldOffset(AtomicInteger.class, "value");

    private volatile int value;
   public final int incrementAndGet() {
        return U.getAndAddInt(this, VALUE, 1) + 1;
    }
    @IntrinsicCandidate
    public final int getAndAddInt(Object o, long offset, int delta) {
        int v;
        do {
            v = getIntVolatile(o, offset);
        } while (!weakCompareAndSetInt(o, offset, v, v + delta));
        return v;
    }
    /** Volatile version of {@link #getInt(Object, long)}  */
    @IntrinsicCandidate
    public native int     getIntVolatile(Object o, long offset);

왜 java의 volitile을 사용하지 않았을까? => 모든 연산은 c++ 코드에서 연산되도록, (java <-> c++ 왔다갔다 @_@)

    /** Volatile version of {@link #getInt(Object, long)}  */
    @IntrinsicCandidate
    public native int     getIntVolatile(Object o, long offset);
@IntrinsicCandidate
    public final boolean weakCompareAndSetInt(Object o, long offset,
                                              int expected,
                                              int x) {
        return compareAndSetInt(o, offset, expected, x);
    }

->

    /**
     * Atomically updates Java variable to {@code x} if it is currently
     * holding {@code expected}.
     *
     * <p>This operation has memory semantics of a {@code volatile} read
     * and write.  Corresponds to C11 atomic_compare_exchange_strong.
     *
     * @return {@code true} if successful
     */
    @IntrinsicCandidate
    public final native boolean compareAndSetInt(Object o, long offset,
                                                 int expected,
                                                 int x);

cas 연산후 +1을 왜 더할까? => c에서 원자적으로 값을 set하고 native 메서드 이후는 jvm에서 delta를 합침(메모리에는 이미 변경되어있음. jvm에 있는 값을 변경하는 것)

원자적?

atomic_compare_exchange_strong

image

inline bool atomic_compare_exchange_strong(volatile atomic_uint32_t *a,
                                           u32 *cmp,
                                           u32 xchg,
                                           memory_order mo) {
  u32 cmpv = *cmp;
  u32 prev = (u32)_InterlockedCompareExchange(
      (volatile long*)&a->val_dont_use, (long)xchg, (long)cmpv);
  if (prev == cmpv)
    return true;
  *cmp = prev;
  return false;
}

image

windows 커널...(소스제공안함..)

interlockedcompareexchange

linux로 변경

image

image

cpu assembly

  • cpu assembly
  • cas
  • 하나의 instruction(=원자적)으로 처리 가능

=> x86 CMPXCHG8B Operation 부분 참조

흐름

SDK Atomic Integer -> byte code -> JVM -> GCC(c++) -> LINUX(c++) -> ASM -> CPU instructions.... 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant