AtomicInteger's getAndIncrement is equivalent to i++, why can guarantee atomicity

Study the underlying source code of this method
Insert picture description here
Insert picture description here
Insert picture description here

AtomicInteger uses CAS but does not need to be synchronized

Consistency with synchronized is guaranteed, but concurrency has dropped a lot.
We use CAS to use do...while to make repeated judgments to ensure consistency and not reduce concurrency.
CAS---->compare And Swap, he is a CPU concurrency primitive. He is not allowed to be interrupted during the execution process, which means that CAS is an atomic instruction on the cpu and will not cause data inconsistency.
CAS Disadvantages:
1. In a high concurrency environment, adding a while loop to judge unsuccessfully makes the cost of the cup extremely large.
2. Only guarantee the atomicity of a shared variable cannot guarantee a piece of code.
3. May cause ABA problems.
Four words summarize the civet cat for the prince.
If t1 and t2 operate on data A at the same time, t1 changes data A to B and updates it to the main memory, but t2 does not know at this time, t1 has updated B to A, and then t2 goes to the main From the memory, A is still okay, so I changed the A in the main memory to his own data. This is the ABA problem

Low-level assembly language
Insert picture description here

The solution to the ABA problem:

There is an AtomicStampedReference class in the atomic class that can solve this problem with a version number.

public class ABADemo {
    /**
     * 这里的Integer不能大于127若大于127则不会出现ABA情况,也就是没有CAS
     * true	128
     * false	128
     */
    private static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);

    private static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100,1);

    public static void main(String[] args) {

        System.out.println("===以下是ABA问题的产生===");

        new Thread(() ->{
            System.out.println(atomicReference.compareAndSet(100, 127)+"\t"+atomicReference.get());

            System.out.println(atomicReference.compareAndSet(127, 100)+"\t"+atomicReference.get());

        },"t1").start();


        new Thread(() -> {

            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(atomicReference.compareAndSet(100, 2019)+"\t"+atomicReference.get());

        },"t2").start();

        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("===以下是ABA问题的解决===");

        new Thread(() ->{
            System.out.println(Thread.currentThread().getName()+"\t第一次版本号:"+atomicStampedReference.getStamp());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(atomicStampedReference.compareAndSet(100, 127,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1)+"\t"+atomicStampedReference.getReference());

            System.out.println(Thread.currentThread().getName()+"\t第二次版本号:"+atomicStampedReference.getStamp());
            System.out.println(atomicStampedReference.compareAndSet(127, 100,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1)+"\t"+atomicStampedReference.getReference());

            System.out.println(Thread.currentThread().getName()+"\t第三次版本号:"+atomicStampedReference.getStamp());

        },"t3").start();


        new Thread(() -> {
            int stamp = atomicStampedReference.getStamp();

            System.out.println(Thread.currentThread().getName()+"\t第一次版本号:"+atomicStampedReference.getStamp());
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(atomicStampedReference.compareAndSet(100, 2019,stamp,stamp+1)+"\t"+atomicStampedReference.getReference());
            System.out.println(Thread.currentThread().getName()+"\t最新的版本号:"+atomicStampedReference.getStamp());



        },"t4").start();


    }
}

Guess you like

Origin blog.csdn.net/qq_36905956/article/details/105857254