Java concurrency - CAS

CAS

1. Introduction to CAS

The full name of CAS Compare And Swap, compare and exchange. It is an atomic instruction of the CPU, and the bottom layer is implemented based on the assembly instructions in the hardware. The CAS algorithm involves 3 operands 内存值V, 预期原值A, 新值B, when the memory value V is equal to the expected value A, update the memory value V to the new value B.

CAS example:

For example: For i = 0 , i++the application of CAS ideas, the thread reads the value of i 0 into the memory, and the original value A=0 is expected.

If V is equal to A, it means that there are no other threads performing i++ operations , so modify V to the new value B, which is 1;

If V is not equal to A, it means that other threads modify the value of i, and there is a concurrency security problem. Give up this modification and try again.

CAS operations are atomic. When multiple threads use CAS to modify data concurrently, there is no need to lock.

2. Problems with CAS

2.1 ABA problem

CAS is to check whether the expected original value A has changed. If the expected original value A is changed to another value C and then modified back to A, the thread will perform CAS comparison and find that the expected original value A has not changed, but has actually changed. .

The essence of the ABA problem is that CAS only checks the initial and final, and does not care about the change of the intermediate state

Why Solve ABA Problems

Assume a scenario: Xiao Ming has 100 yuan in his account and is going to withdraw 50 yuan. In the case of concurrent multi-threading, thread A and thread B both check the balance to be 100. Thread A successfully withdraws 50. Under normal circumstances, thread B should fail, but this If Xiao Ming's account receives 50 yuan, then thread B will succeed when using CAS for comparison, and another 50 yuan will be deducted. The result is that Xiao Ming withdraws 50 but deducts 100 yuan.

Solutions to ABA Problems

Use the version number to identify the state of the variable. For example, if A1 is changed to C2 and then changed back to A3, the ABA problem is solved if A1 and A3 are not equal.

Using AtomicStampedReferenceclasses to solve ABA problems

public class AtomicStampedReference<V> {
    
    

    private static class Pair<T> {
    
    
        final T reference;   // 对象引用
        final int stamp;    // 用于标志版本号
        private Pair(T reference, int stamp) {
    
    
            this.reference = reference;
            this.stamp = stamp;
        }
        static <T> Pair<T> of(T reference, int stamp) {
    
    
            return new Pair<T>(reference, stamp);
        }
    }
  / **
    *   ......
    */
      // pair使用volatile保证可见性
    private volatile Pair<V> pair;
    
        public boolean compareAndSet(V   expectedReference,  // 更新前的值
                                 V   newReference,    // 更新后的值
                                 int expectedStamp,   // 预期的版本号
                                 int newStamp) {
    
            //更新后的版本号
           // 获取当前元素值 + 版本号  
         Pair<V> current = pair;
        return
            expectedReference == current.reference &&   // 比较引用
            expectedStamp == current.stamp &&        // 比较版本号
            ((newReference == current.reference &&    // 新引用等于旧引用
              newStamp == current.stamp) ||          // 新版本号等于旧版本号
             // 创建新的pair对象并CAS更新
             casPair(current, Pair.of(newReference, newStamp))); 
    }
}

compareAndSet方法Results of the:

  • If the element value and version number have not changed and are the same as the new one, it means it has CASbeen updated and returnstrue
  • If the element value and version number have not changed and are different from the new one, create a new one Pairand initialize it to the new value and version number
  • other returnfalse

2.2 Only one atomic operation of a shared variable can be guaranteed

When the CAS operation is performed on multiple shared variables, the atomicity of the operation cannot be guaranteed, such as the operation on two or more variables and the operation on the code block.

solution

Java1.5Finally, a class JDKis provided AtomicReferenceto ensure the atomicity between referenced objects, and multiple variables can be placed in one object for atomic operations.

synchronizedYou can choose to use or lock for code blocks Lock .

2.3 Long cycle time and high overhead

CASGenerally, loop operations are used to continuously retry (such as spin locks). If the time is long, the overhead of CPU resources will be increased.

Optimization

You can set the number of spins, the default is 10 times. JVMProvides adaptive spin locks, automatically adjusts the number of cycles, and can determine whether to use the number of times or not CASaccording to the previous CASexecution of the same lockCASCAS

Guess you like

Origin blog.csdn.net/qq_52595134/article/details/128424488