What CAS that? Generating and solutions ABA problem

What CAS that?

Compare and exchange (compare and swap) is a CPU concurrency primitives

Features

Determine the value of a memory location if the expected value, and if it changes to a new value, the process is atomic, the middle will not break the promise to solve the problem of data consistency.

The underlying principle

Unsafe Deliverable

CAS is the core classes, since no direct access to the underlying java system, need access through a local (Native) method, the Unsafe equivalent to a backdoor, the operation of a particular class direct memory data. Method sun.misc Unsafe class exists in the package, a method of operating the internal memory can be operated directly as a pointer image C, as the CAS java class depends on Unsafe

Note that all methods are native in Unsafe modification, that are the direct method Unsafe in the underlying operating system resources to perform tasks

The underlying compilation

Underlying code

 // AtomicInteger类中方法:getAndIncrement,调用Unsafe类中的getAndAddInt
 public final int getAndIncrement(){
     return unsafe.getAndAddInt(this,valueOffset,1);
}
//Unsafe类中
 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;
}

Explanation:

  • var1 is the object itself AtomicInteger

  • var2 value of the object is referenced address

  • var4 is the desired value changes

  • var5 by var1, the true value of the memory identified var2 Method: comparing a target value and var5, if the same, then the update var5 + var4 and returns TRUE, if different then continues to compare values, until the update carry out

 

 

 

 

Shortcoming

1, the cycle time spending big

2, to ensure that only a shared variable atomic operation

3, leads ABA problem

 

ABA problem

CAS algorithm is an important prerequisite for a certain time required to extract the data in memory and compare and replaced at the present moment, then within this time difference can lead to changes in the data.

For example:

One thread taken from a memory location V A, which is also removed when another thread A two from memory, and some of the operations performed two threads to become A to B, and then move into a position data V A, and this time, when one thread perform the operation CAS found that memory still is a, then the success of one thread prompts.

Although one thread CAS operation is successful, but it does not mean that this thread is not the problem

 

Code reduction

package com.dayu.inter;

import sun.rmi.runtime.NewThreadAction;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @Author: dayu
 * @Date: 2019/9/24 15:13
 * @Description
 */
public class ABADemo {

    public static void main(String[] args) {
        System.out.println("=========下面是ABA问题的产生==========");
        AtomicReference<Integer> atomicReference = new AtomicReference<>(100);
        new Thread(() -> {
            System.out.println(atomicReference.compareAndSet(100, 101)+"\t"+atomicReference.get());
            System.out.println(atomicReference.compareAndSet(101, 100)+"\t"+atomicReference.get());
        }, "t1").start();

        new Thread(() -> {
            //休息一会,让线程t1先执行一遍ABA的问题
            try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}

            System.out.println(atomicReference.compareAndSet(100, 2000)+"\t"+atomicReference.get());
        }, "T2" ) .start (); 

        // a break, to ensure completion of the above two threads executing 
        the try {TimeUnit.SECONDS.sleep (2);} the catch (InterruptedException E) {e.printStackTrace ();} 
        
        the System.out .println ( "========= ========== ABA below to solve the problem" );
         // somewhat similar to the optimistic lock
         // initial value of 100, the time stamp ( The version number. 1 =) 
        An AtomicStampedReference <Integer> = AtomicStampedReference new new An AtomicStampedReference <> (100,. 1 );
         new new the Thread (() -> {
             int Stamp = atomicStampedReference.getStamp (); 
            System.out.println (Thread.currentThread (). getName () + "\ t first get the version number" +Stamp); 
        
            // rest, waiting t4 get the version number 
            the try {TimeUnit.SECONDS.sleep (. 1);} the catch (InterruptedException E) {e.printStackTrace ();} 
            atomicStampedReference.compareAndSet ( 100, 101, atomicStampedReference.getStamp () , atomicStampedReference.getStamp () +. 1 ); 
            . System.out.println (Thread.currentThread () getName () + "\ T 2nd get the version number" + atomicStampedReference.getStamp ()); 
            atomicStampedReference.compareAndSet ( 101,100, atomicStampedReference.getStamp (), atomicStampedReference.getStamp () +. 1 ); 
            . System.out.println (Thread.currentThread () getName () + "\ T 3rd get the version number" + atomicStampedReference.getStamp());
        }, "T3" ) .start ();

        // consistent t3 and t4 initial version number acquired, 
        new new the Thread (() -> {
             int Stamp = atomicStampedReference.getStamp (); 
            . System.out.println (Thread.currentThread () getName () + "\ T section obtaining a version number of "+ Stamp); 

            // a break, to ensure a complete t3 the ABA 
            the try {TimeUnit.SECONDS.sleep (. 4);} the catch (InterruptedException E) {e.printStackTrace ();}
             Boolean Result = AtomicStampedReference .compareAndSet (100, 2019, Stamp, Stamp + 1 ); 
            System.out.println (Thread.currentThread () getName (). + "\ t whether to amend the success:" + result + "\ t the current real version:" + atomicStampedReference.getStamp ()
             + "\ t the current real value:"+atomicStampedReference.getReference());
        }, "t4").start();


    }
}

 

In order to solve the problem of ABA, plus a version number in the atomic reference to the class, this is somewhat similar to the mysql as optimistic locking, each thread needs to change the time to change the version number, so many threads to get the same version number when only a thread can successfully changed.

 

Guess you like

Origin www.cnblogs.com/dayu007/p/11578871.html