CAS ABA problem of what harm?

CASE

CAS (CompareAndSet) is to ensure the safety of a CPU complicated by underlying atomic instructions , its function is to determine whether a value is the expected value, if it is, then it changed to the new value will not be interrupted in the CAS process.

compareAndSet implemented in JNI (Java Naive Interface), located unsafe.cpp file, the key phrase is cmpxchg (x, addr, e), where x refers to the old value, addr is to be consistent and oldValue memory location, and e It is to become the new value. The atomic statement is executed, and the values ​​extracted from oldValue addr compare equal, then only the position is set addr new value e.

ABA

But CAS ABA there is a problem, for example, assume that thread 1 and thread 2 have the same reference p, p points to an object A. At some point, want to use the CAS to thread 1 objects p points into C, this time was interrupted thread 2, thread 2 p pointed objects into B and then into A, then thread 1 to continue running, find p indeed still point to the object A, and therefore the implementation of CAS will replace C. A Thread 1 but does not know at this time it is interrupted, p reference point experienced a problem from A to B to A in the process, this bug is called the ABA. For ordinary scene is, ABA problem does not seem to cause any harm, but we consider this scenario below.

ABA hazards

Here is a pseudo-code, we will look forward to. Scenario is to implement a linked list stack, the stack is pressed into the initialization B, A two elements, point A head stack elements.

After a moment, trying to thread a top of the stack into B, but it gets oldValue top of the stack (as A), thread 2 is interrupted. Thread 2 sequentially A, B released, and then pressed into the C, D, A. Then change the thread continues to run 1 thread 1 execution compareAndSet found head element pointed indeed consistent with oldValue, are A, it will head to point B a. However, I note that the line of code marked yellow, thread 2 in the pop-B, when the next set B is null, so after the thread 1 will head to point B, the stack only elements of a lone B. However, as expected, the stack should be put B → A → D → C.

 

Node head;
head = B;
A.next = head;
head = A;


Thread thread1 = new Thread(
    ->{
          oldValue = head;
          sleep (3 seconds);
          compareAndSet(oldValue, B);

    }
);

Thread thread2 = new Thread(
    ->{
        // 弹出A
          newHead = head.next;
          head.next = null ; // i.e. null = A.next; 
          head = newHead;
          // pop B 
          newHead = head.next;
           head.next = null ; // i.e. null = B.next; 
          head = newHead; // At this head is null
          
          // press-C 
          head = C;
           // pressed D 
          D.next = head;
          head = D;
           // pressed A 
          A.next = D;
          head = A;
          

    }
);

thread1.start();
thread2.start();

 

If wrong, please correct me>. <

Guess you like

Origin www.cnblogs.com/yingying7/p/12573240.html