Solution of ABA problem in CAS

From ( here )    the generation of CAS problems

 

There is a classic ABA problem in using CAS for Lock-Free operation:

Thread 1 is ready to use CAS to replace the value of the variable from A to B. Before that, thread 2 replaces the value of the variable from A to C, and then from C to A. Then thread 1 found that the value of the variable is still as A, so CAS is successful. But in fact, the scene at this time is different from the original. Although CAS is successful, there may be hidden problems, such as the following example:

There is a stack implemented with a singly linked list. The top of the stack is A. At this time, thread T1 already knows that A.next is B, and then wants to use CAS to replace the top of the stack with B:

head.compareAndSet(A,B);

Before T1 executes the above instruction, thread T2 intervenes, pushes A and B off the stack, and then pushD, C, and A. At this time, the stack structure is as shown below, while object B is in a free state at this time:

At this time, it is the turn of thread T1 to perform the CAS operation, and the detection finds that the top of the stack is still A, so CAS is successful, and the top of the stack becomes B, but in fact B.next is null, so the situation at this time becomes:

Among them, there is only one element in the stack, and the linked list composed of C and D no longer exists in the stack, and C and D are thrown away for no reason.

The above is the hidden danger caused by the ABA problem. In the implementation of various optimistic locks, the version stamp is usually used to mark records or objects to avoid the problems caused by concurrent operations. In Java, AtomicStampedReference <E> also implements this Function, it stamps the version of the object by wrapping the tuple of [E, Integer] to avoid ABA problems. For example, the following code uses AtomicInteger and AtomicStampedReference to update the atomic integer variable with an initial value of 100 The CAS operation will be successfully performed, and the version stamped AtomicStampedReference will fail to execute the CAS for the ABA problem:

public class Test {
    private static AtomicInteger atomicInt = new AtomicInteger(100);
    private static AtomicStampedReference atomicStampedRef = new AtomicStampedReference(100, 0);

    public static void main(String[] args) throws InterruptedException {
       Thread intT1 = new Thread(new Runnable() {
           @Override
           public void run() {
              atomicInt.compareAndSet(100, 101);
              atomicInt.compareAndSet(101, 100);
           }
       });

       Thread intT2 = new Thread(new Runnable() {
           @Override
           public void run() {
              try {
                  TimeUnit.SECONDS.sleep(1);
              } catch (InterruptedException e) {
              }
              boolean c3 = atomicInt.compareAndSet(100, 101);
              System.out.println(c3); // true
           }
       });

       intT1.start();
       intT2.start();
       intT1.join();
       intT2.join();

       Thread refT1 = new Thread(new Runnable() {
           @Override
           public void run()
              try {
                  TimeUnit.SECONDS.sleep(1);
              } catch (InterruptedException e) {
              }
              atomicStampedRef.compareAndSet(100, 101, atomicStampedRef.getStamp(), atomicStampedRef.getStamp() + 1);
              atomicStampedRef.compareAndSet(101, 100, atomicStampedRef.getStamp(), atomicStampedRef.getStamp() + 1);
           }
       });

       Thread refT2 = new Thread(new Runnable() {
           @Override
           public void run() {
              int stamp = atomicStampedRef.getStamp();
              try {
                  TimeUnit.SECONDS.sleep(2);
              } catch (InterruptedException e) {
              }
              boolean c3 = atomicStampedRef.compareAndSet(100, 101, stamp, stamp + 1);
              System.out.println(c3); // false
           }
       });

       refT1.start();
       refT2.start();
    }

PS: AtomicStampedReference solves the CAS ABA problem.In fact, it is not successful when the ABA problem occurs, instead of automatically correcting the problem.

Guess you like

Origin www.cnblogs.com/max-home/p/12720374.html