What is CAS

CAS (Compare And Swap) Compare and swap

CAS is a CPU concurrency primitives. Function is to determine whether a memory location of the value of the expected value, and if it changes to the latest value, the process is atomic. CAS concurrency primitives that reflect each local method sun.misc.Unsafe class in the Java language. This is a completely dependent on 硬件the function of the atomic operation through it. Continuous, in the implementation process not be interrupted during implementation of the original language, that CAS is a CPU of atomic instructions, it will not cause data inconsistencies.

CAS role is to compare the current value of the value of working memory and main memory, then the implementation of the provisions if the same operation, otherwise the comparison continues until the agreed value of the main memory and working memory until. If you look at this statement I do not know what to say, then continue to look down, look throughout the end of this sentence to read it.

This one to explore the CAS in the end is how to achieve AtomicInteger by two methods.

Two methods of AtomicInteger

compareAndSet

First look at three lines of code

AtomicInteger atomicInteger = new AtomicInteger(5);
System.out.println(atomicInteger.compareAndSet(5,10)+ "\t current data : " +atomicInteger.get());
System.out.println(atomicInteger.compareAndSet(5,9)+ "\t current data : " +atomicInteger.get()); 
复制代码

The articles of volatile understanding mentioned, you can use atomic class AtomicInteger solve atomic problems. AtomicInteger.compareAndSet method used here, two parameters are 期望值and 更新值, if 期望值the case is the same as the value in memory, then the memory value is updated 更新值, the method returns a boolean value indicating whether the update was successful. More than three lines of code, provided the value of the memory 5 is initialized with the updated value of the second line of the expected value of 5 and 10, updates the value if the value of the expected value in memory 5 and 5 the same, then the memory 10, the second OK returns true, the current value memory 10; the third line 5 is the desired value, the current value in memory 10, does not meet the expected results, the results of the memory is not updated, it returns false, the current value of the memory is not changed or 10. The output code is as follows:

true	 current data : 10
false	 current data : 10
复制代码

Outline, CAS involves three operands, memory value V, the expected value of the old A, to modify the updated value of B. If and only if the expected value of the A and V are the same memory value, the memory value V revised to B, or do nothing.

getAndIncrement

We know that in the case of multi-threaded i++operation actually consists of three steps, the thread is unsafe. We can use atomicInteger.getAndIncrement()to achieve thread-safe i++, to know how to do the following thread-safe look by implementing the method.

    /**
     * Atomically increments by one the current value.
     *
     * @return the previous value
     */
    public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
    }
复制代码

These are getAndIncrement source code, adding a comment based on the current value on the atom. Implemented invoking unsafeclass getAndAddIntmethod that has three parameters, namely the current object, the memory offset, 1, and then look down, proceeds to unsafe class.

  1. unsafe class
    unsafe CAS classes are core classes. java is unable to access the underlying system, and you need to access through your local (native) methods, all of Unsafe are native to modify, that is the basis of the method Unsafe class are direct calls to the underlying operating system resources to perform the appropriate task, That can be like a C pointer as direct access memory.
  2. Variable valueOffset, indicates that the variable value of the offset address in memory, because that is acquired Unsafe data according to the memory address offset. The following code shows the origin of valueOffset
private static final long valueOffset;

    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

    private volatile int value;
复制代码
  1. Variable value with volatile modified to ensure the visibility of memory across multiple threads. So to get the memory address is always up to date.

Understand these concepts, we continue to look down, getAndAddIntit is how to achieve:

    public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

        return var5;
    }
复制代码

This is still present in unfase method, var1 corresponding to this, i.e. the current object, var2 is a memory offset, var4 i.e. to add "1."
Current methods for the do-while structure, according to the method name getAndAdd, first getoperation, do the structure first acquires the current value var5 depending on the object and the memory address is copied from the physical main memory into its own thread working memory; and the key points of: while inside this moment is determined if the value of the memory address var5 same, is modified to var5 + var4, i.e. Addsuccessful, then returns true, while inverted, the condition is not satisfied, do not executed; if the value var5 just received, the master value of the physical memory on the change, i.e., the main memory and the values do not match var5, not modified, returns false, while conditions are met, proceed to do the operation, to obtain the latest current value of the memory again, is determined to continue until the guaranteed plus when the latest results of the moment get.
The above operation simply, is to get var5, then var5 + 1, worried about the value of var5 has changed a plus when operating, so add a moment again to verify it again, if the value or var5 then rest assured that the memory of this plus a operation, or to stop to get the latest value.

Below is an example to explain the particular piece of content:

Suppose thread A and thread B getAndAddInt two threads execute operations:

  1. AtomicInteger inside original value is 3, i.e. the main memory AtomicInteger value of 3, according to JMM model (refer to the article understanding of the volatile ), thread A and thread B are each holding a value of 3 replicas of the value their working memory.
  2. A thread through getIntVolatile(var1,var2)get value is 3, which is A is suspended.
  3. By thread B also getIntVolatile(var1,var2)get value is 3, then B is not just suspended with a thread and performing compareAndSwapIntthe method is also a comparison value memory 3, it is successfully modified memory 4, the thread B to complete the operation.
  4. A thread is then recovered and execution compareAndSwapIntmethods, found themselves working memory numbers 3 and number 4 in the main memory is inconsistent, indicating that the value has been modified by another thread preemption, then A thread of this modification fails 重新读取最新值重来一遍, that re do perform the operation.
  5. A thread reacquisition value value, because the variable value is modified volatile, so the other thread to his modification, thread A can always see the first time, the thread A executed compareAndSwapIntby comparing replacement, until successful.

And then outline, CAS has three operands, memory value V, the expected value of the old A, to modify the updated value of B. If and only if the expected value of the A and V are the same memory value, the memory value V revised to B, or do nothing. Then re-opening to see whether that sentence would understand it.

CAS shortcomings

  1. Long cycle time much overhead
    • According to the source code can be seen, the internal structure of do-while, while if the conditions are not met has been trying to acquire a new value, because the CAS did not lock, there may be multiple threads to modify the value of memory when multiple threads at the same time when do block of code in continuous cycle, to a great deal of CPU overhead. The synchronized at the same time only one thread at a real value to modify memory is guaranteed.
  2. Atomic operation can only guarantee a shared variable
    • Since the getAndAddIntfirst argument is the Object, i.e. this represents the current object, the number of terms here can control a shared variable. The synchronized lock to lock a section of code, you can ensure that multiple threads are locked.
  3. ABA lead out problem
    • ABA problem: To 5 A thread 10 is modified, it is get into memory 5, which is suspended; thread B from the value of the memory 5 to 6, then from 5 to 6, B a meal after the operation while obtaining resources to continue into the judge found that the value of memory with the same value or 5 held their own hands, it can be updated more action 5 10. A seems to get in the middle and set the operation has not changed, get a 5, or 5 set when, in fact, the value of which has been changed.尽管线程A的CAS操作成功,但是不代表这个过程就没有问题。

Guess you like

Origin juejin.im/post/5cfe78c55188257e853fa95d