Some understanding of CAS mechanism

Multithreading practice

public class test {
    private static int x;
    public static void main(String[] args) throws InterruptedException {
        Thread task1 = new Thread(){
            @Override
            public void run(a) {
                super.run();
                for (int i=0; i<1000; i++){
                    x=x+1; }}}; Thread task2 =new Thread(){
            @Override
            public void run(a) {
                super.run();
                for (int i=0; i<1000; i++){
                    x=x+1; }}}; task1.start(); task2.start(); task1.join(); task2.join(); System.out.println(x); }/ * * / 1006/ / : ~
Copy the code

Two threads start at the same time, add x, ideally, the output should be 2000, but it ends up being 1006, because if you have multiple threads, you can add two threads at the same time.

public class test {
    private static AtomicInteger atomicInteger = new AtomicInteger();
    public static void main(String[] args) throws InterruptedException {
        Thread task1 = new Thread(){
            @Override
            public void run(a) {
                super.run();
                for (int i=0; i<1000; i++){ atomicInteger.incrementAndGet(); }}}; Thread task2 =new Thread(){
            @Override
            public void run(a) {
                super.run();
                for (int i=0; i<1000; i++){ atomicInteger.incrementAndGet(); }}}; task1.start(); task2.start(); task1.join(); task2.join(); System.out.println(atomicInteger.get()); }}/ * * / 2000/ / : ~
Copy the code

Modify the accumulated object X to AtomicInteger, resulting in an ideal 2000. Locks are not used in this operation because AtomicInteger introduces the CAS mechanism.

What is the CAS mechanism

The CAS mechanism simply says, compare swap, have expected value, old value and memory location; Take the old value and swap it for the new value.

Why is AtomicInteger thread safe

Source:

private static final longvalueOffset; .public final int incrementAndGet(a) {
    return unsafe.getAndAddInt(this, valueOffset, 1) + 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;
}
Copy the code

ValueOffset is a hardcoded atomic operation, and incrementAndGet calls unsafe.getAndAddInt, which is implemented using the CAS mechanism. Var5 retrievals the latest current value from the main memory. This value is visible and shared by all threads, swapped with var4, and spins until the update succeeds on failure.

Graphical CAS mechanism

As you can see, CAS is thread safe without using any locks. CAS has many advantages, but also many disadvantages, such as ABA problems

ABA problem

What are ABA problems

Actually, it’s easy to understand, A->B->A, the value of A has not changed, but it has undergone some kind of operation.

The illustration

What effect does it have

Threads 1, 2, and 3 above all do their job without a problem. But if they were transferring money, there was a problem, and $10 was missing from the account.

To solve

Introduce the version number, can solve the problem, every time there is the same value, do a version accumulation, as long as the version number does not match is changed.

conclusion

Advantages: Avoid the consumption disadvantage of locking when concurrency is not very high:

  1. In the case of high concurrency, if the modification fails for several times, the CPU consumption will continue
  2. Only atomic level safe changes can be made to variables, not code blocks.