java concurrency - learning CAS

Learn CAS

What is a CAS Dian

   CAS (Compare And Swap) that is relatively exchange, given a desired value, when you want to modify variable values ​​and expectations consistent (that other threads do not modify) on the modification of variable values ​​corresponding, or do nothing, which allows try again comparison of exchange, until it succeeds.

 

Two Dian CAS algorithmic process

  CAS (V, E, N). V represents a variable to be updated, E represents an expected value, N represents a value to be updated.

  Only when V = E, the V will be updated to N, if V ≠ E, explained there are other threads updated V, the current thread do nothing. Finally CAS returns the current real value of V

 

Wed and pessimistic locking and optimistic locking

  For concurrency control, pessimistic locking is a strategy, it is always possible to think multithreading conflict, so always lock control, blocking wait.

   No lock is an optimistic strategy, it is always considered multithreading rarely conflict, no lock, if there is a conflict, re-try the operation again until no conflict can be.

  No lock mainly the use of CAS implementation, it is an "optimistic locking"

   

  No lock advantages:

  1. no deadlocks

  2. There is no overhead caused by lock contention

  3. There is no overhead frequent scheduling between threads brought

  4. superior performance

  

 Dian four CPU instruction support

  At the hardware level, most modern processors have support of CAS atomic instructions. After JDK5.0, the virtual machine can use this command to achieve concurrent operation and concurrent data structures, and such an operation in a virtual machine It can be said to be everywhere.

   

Five categories Dian unsafe

   CompareAndSet AtomicInteger source inlet () method (JDK 8)

 /**
     * Atomically sets the value to the given updated value
     * if the current value {@code ==} the expected value.
     *
     * @param expect the expected value
     * @param update the new value
     * @return {@code true} if successful. False return indicates that
     * the actual value was not equal to the expected value.
     */
    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

  

  unsafe class is an insecure, jdk does not allow developers to access its internal pointer method can be like a direct memory operation information -.. < Java becomes complicated - no lock CAS >

  The unsafe compareAndSwapInt () method, internal CAS atomic instructions to complete

public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x);

The first parameter a o of the given object , offset is the offset within an object (by an offset , can be acquired quickly locate the corresponding field variables ), represents the expected value expected , x represents a value to be set . If the specified field the value is equal to expected, it will set it to x

  

 Atomic six atoms class Dian

   Thread-safe operation is achieved Atomic atoms classes are using the CAS operation, unsafe level calls a class method, the use of unsafe instructions atoms CAS

  To AtomicInteger for example, internal records to maintain a modified using the volatile keyword int variables, (volatitle only guarantee visibility between threads, a thread that is to modify the variable, another thread can know, but it does not guarantee atomicity)

   AtomicInteger thread-safe method of increment

/**
     * Atomically increments by one the current value.
     *
     * @return the updated value
     */
    public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }

 

  unsafe in getAndAddInt () method

    public  Final  int getAndAddInt (Object O, Long offset, int Delta) {
         int Curr;
         do { 
            Curr = the this .getIntVolatile (O, offset); // the use of volatile, modify operation of each thread can be perceived 
        } the while (! the this .compareAndSwapInt (O, offset, Curr, Curr + Delta)); // if cas operation is not successful attempts continue, compareAndSwapInt () method, see section explains a fifth 

        return Curr; 
    }

 

 

Seven Dian ABA problem

   Suppose the initial value of a variable v 0, t1, t2 thread reads the value is 0, since the other thread scheduling issues, t1 cas did not continue the operation, using the cas t2 during operation, will be incremented by one, v 1, thread v t3 Save operation using cas 1 becomes 0 after t1 cpu continue obtained when using cas operation t1, v value is still 0 found, that no change in v, actually has changed, so that there will be some scenes problem, which is the ABA problem

   Use an object with a time stamp references AtomicStampedReference can effectively solve the problem, internal AtomicStampedReference addition to maintaining the value of the object, but also to maintain a timestamp (actual identity can be any integer value to represent the state, can also be a version number). AtomicStampedReference in outside the update target value, you must also update the timestamp before updating the value of the object, in addition to the comparison value, you must also compare the time stamp, and only in the case of these two conditions are equal, will go to update the values, or that the modified by other threads

 

Eight Dian example

 

public class AddCASRunnable implements Runnable {
    private AtomicInteger data =new AtomicInteger(0);


    public int getResult(){
        return data.get();
    }

    @Override
    public void run() {
        for(int i=0;i < 10000000; i++){
            data.incrementAndGet();
        }
    }
}

 

public class AddUnsafeRunnable implements Runnable {
    private int data=0;

    public int getResult(){
        return data;
    }

    @Override
    public void run() {
        for(int i=0;i < 10000000; i++){
            data++;
        }
    }
}

 

public class Client {

    public static void main(String[] args) throws InterruptedException {

        AddCASRunnable addCASRunnable=new AddCASRunnable();
        Thread t1=new Thread(addCASRunnable);
        Thread t2=new Thread(addCASRunnable);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("CAS 结果为: "+addCASRunnable.getResult()); // CAS 结果为: 20000000


        AddUnsafeRunnable addUnsafeRunnable=new AddUnsafeRunnable();
        Thread t3=new Thread(addUnsafeRunnable);
        Thread t4=new Thread(addUnsafeRunnable);
        t3.start();
        t4.start();
        t3.join();
        t4.join();
        System.out.println("unsafe 结果为: "+addUnsafeRunnable.getResult()); // unsafe 结果为: 19994931

    }

}

 

  源码地址为: https://gitee.com/timfruit189/java-learning/tree/master/src/main/java/com/ttx/java/concurrent/cas

 

 

学习资料:

  <java高并发程序设计> 葛一鸣 郭超 编著

  <java并发变成-无锁CAS>

 

Guess you like

Origin www.cnblogs.com/timfruit/p/10962986.html