Java cas principle

There are many atomic classes AtomicInteger.java under the JDK concurrent package, which provide atomic update operations.

The following is a cas demo method

public  static  void casDemo(){
        AtomicInteger atomicInteger = new AtomicInteger(1);
        int x = atomicInteger.getAndIncrement();
        System.out.println("x = " + x);
    }

Here getAndIncrement will give 1 by itself and is thread-safe.

Follow up JDK source code

AtomicInteger.getAndIncrement() method

/**
     * Atomically increments the current value,
     * with memory effects as specified by {@link VarHandle#getAndAdd}.
     *
     * <p>Equivalent to {@code getAndAdd(1)}.
     *
     * @return the previous value
     */
    public final int getAndIncrement() {
        return U.getAndAddInt(this, VALUE, 1);
    }

The annotation shows that the function of the method is to atomically update the variable, and continue to follow the U.getAndAddInt() method

/**
     * Atomically adds the given value to the current value of a field
     * or array element within the given object {@code o}
     * at the given {@code offset}.
     *
     * @param o object/array to update the field/element in
     * @param offset field/element offset
     * @param delta the value to add
     * @return the previous value
     * @since 1.8
     */
    @HotSpotIntrinsicCandidate
    public  final  int getAndAddInt (Object o, long offset, int delta) {
         int v;
        to {
            v = getIntVolatile (o, offset);
        } while (!weakCompareAndSetInt(o, offset, v, v + delta));
        return v;
    }

The JDK 10 I use here may be a little different, continue to follow the weakCompareAndSetnt() method

@HotSpotIntrinsicCandidate
    public final boolean weakCompareAndSetInt(Object o, long offset,
                                              int expected,
                                              int x) {
        return compareAndSetInt(o, offset, expected, x);
    }

Continue to follow up the compareAndSetInt() method

/**
     * 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
     */
    @HotSpotIntrinsicCandidate
    public final native boolean compareAndSetInt(Object o, long offset,
                                                 int expected,
                                                 int x);

Here is a native method, a native method, that is, a native method, that calls methods implemented in other languages. It can be seen from openjdk that jvm is mainly implemented by C++. I saw others posted the openjdk source code on the Internet.

// Adding a lock prefix to an instruction on MP machine
// VC++ doesn't like the lock prefix to be on a single line
// so we can't insert a label after the lock prefix.
// By emitting a lock prefix, we can define a label after it.
#define LOCK_IF_MP(mp) __asm cmp mp, 0  \
                       __asm ​​is L0 \
                       __asm _emit 0xF0 \
                       __asm ​​L0:

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
    mov ecx, exchange_value
    mov eax, compare_value
    LOCK_IF_MP(mp)
    cmpxchg dword ptr [edx], ecx
  }
}

In this source code, you can see that the compiled cmpxchg instruction is used. In the case of multiple CPUs, the lock prefix will be added before the instruction to ensure the atomicity of instruction execution. Single-core CPUs will not be prefixed with lock.

How to ensure the atomicity of this instruction is a matter of the CPU. There is information on the Internet that it locks the bus, locks the shared memory, etc.

cas advantages:

1. No thread blocking, no thread context switching

shortcoming:

1. Thread spin, cpu idling

2. The atomicity of multiple variables is not guaranteed

3. Can't perceive the ABA problem, you can consider using the version number to solve it

 

refer to

1. http://zl198751.iteye.com/blog/1848575

2. https://blog.csdn.net/xiuye2015/article/details/53406432

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325615646&siteId=291194637