java - CAS and CAS underlying principle

What CAS that?

  The full name CAS Compare-And-Swap it is a CPU concurrency primitives, i.e. the hardware level, the CPU determines whether or not to set a new comparative value and this operation is atomic in nature, it will not be interrupted by other threads. JAVA and contract in the bottom java.util.concurrent.atomic cause data is used when a CAS Mansian mechanism to avoid concurrent computing.

atomic underlying implementation

Under each category are mainly used java.util.concurrent.atomic UnSafe class to Compare-And-Swap operation.
Unsafe in Java an underlying class, contains many basic operations, such as array operations, object operations, memory operations, CAS operation, the thread (Park) operation, the fence (Fence) operation, the JUC package, some of the tripartite framework uses Unsafe class concurrent to ensure safety. Unsafe class in more than one class in the jdk source used to provide some of the more low-level functionality to bypass the JVM of this class, based on its implementation can improve efficiency. However, it is a double-edged sword: As its name indicates it, it is Unsafe, and what it will need to manually allocate memory free (not to be recovered GC). Unsafe class, provides a simple alternative to JNI certain features: at the same time ensure efficiency, making things easier.
If you need to customize atoms may be referenced by generic class provided by AtomicReference herein, this is not too much introduction.
Next to AtomicInteger class as a starting point to see how Atomic using Compare-And-Swap to ensure concurrency safety.

public class AtomicInteger extends Number implements java.io.Serializable {
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;
    //1.objectFieldOffset()方法用于获取某个字段相对Java对象的起始地址的偏移量。
    //2.下次访问将直接通过this对象与相对偏移量直接从内存访问value的值。从不经过JVM虚拟机。
    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }
    private volatile int value;
    
    .
    .
    .
    //调用unsafe对预期值进行判断,如果判断成功则将值设置进去。
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }
    //调用unsafe.getAndAddInt方法,该方法内部采用自旋锁不断compareAndSet当设置成功后才跳循环,否则不断得查询并且计算然后进行compareAndSet。
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }
public final class Unsafe {
    .
    .
    .
    public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
    public native int getIntVolatile(Object var1, long var2);
    //通过一个死循环不停的获取值并且计算然后比较是否能够设置否则继续如此操作。
    public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        //compareAndSwapInt是Unsafe类利用计算机底层实现的,该操作是具有原子性,所以不必担心并发问题。
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
        return var5;
    }
}

CAS shortcomings

Because CAS is not as synchronized lock the entire method, other threads in a wait lock released state. Therefore, the CAS will increase concurrency. But at the same time in concurrency enhancements will be accompanied by some drawbacks.

  1. Long cycle time, CPU overhead increases.
  2. Atomic operation can only guarantee a shared variable.
  3. ABA leads to problems.

ABA problem

Suppose there is such a variable whose initial value is a 1, two threads are thread A and thread B, A calling thread cycle is much lower than the thread B.

order A thread Thread B
1 a=getIntVolatile(0)
2 a=getIntVolatile(0)
3 this.compareAndSwapInt(var1, var2, a, 1)
4 a=getIntVolatile(1)
5 this.compareAndSwapInt(var1, var2, a, 0)
6 this.compareAndSwapInt(var1, var2, a, 2)

For thread B is able compareAndSwapInt successful he can not perceive thread A will be a variable to 1 and then set to 0 process, thread B only concerned with the results, as long as the time to perform in line with the expected value compareAndSwapInt can set the value inside.

ABA Problem Solving

ABA solve the problem of which the idea is to introduce version control. For every successful conduct of compareAndSet the version number is incremented by 1, then each took the version number do match expectations, so it can avoid the ABA problem. Fortunately, at the same java.util.concurrent.atomic package has been promising us a version number based on a reference atomic action class AtomicStampedReference.

//创建出AtomicStampedReference实例,参数分别为初始值和初始版本号
AtomicStampedReference<Integer> atomicStampedReference=new AtomicStampedReference(100,1);
//获取当前版本号
int stamp=atomicStampedReference.getStamp();
//执行比较并且设置参数分别为期望值,设置新值,期望版本号,设置新版本号
atomicStampedReference.compareAndSet(100,200,stamp,stamp+1)

Guess you like

Origin www.cnblogs.com/cjunn/p/12231383.html