CAS compareandse source code analysis

Posted by yepster123 on Wed, 23 Feb 2022 11:51:15 +0100

What is CAS?

There should be two first reactions:
1. Cas single sign on. Of course, this aspect will not be discussed this time;
2. compareAndSet method is the correct way for us to learn code by learning its API first and then mastering its principles. We should not be affected by the cramming teaching when we were young. It is different from learning mathematics, English and other knowledge subjects. Therefore, we can directly come to a section of code:

CAS API usage:

	//Atomic operation
	AtomicInteger atomicInteger = new AtomicInteger(5);
	//The expected value is 5. If it is the same as 5, it will be changed to 2019
	System.out.println(atomicInteger.compareAndSet(5, 2019)+"\t current data:"+atomicInteger.get());
	System.out.println(atomicInteger.compareAndSet(5, 1024)+"\t current data:"+atomicInteger.get());
	atomicInteger.getAndIncrement();

Combined with the following graphical solutions, learn about the usage of relevant API s:

Through this demonstration, we should have understood the basic usage of cas:

The full name of CAS is compare and swap, which is a CPU concurrency primitive.
Its function is to judge whether the value of a certain location in memory is the expected value. If so, it will be changed to a new value. This process is atomic.

One sentence summary: under multithreading, if the data is the same as that in physical memory, it will be modified; otherwise, it will not be modified

CAS principle

1. View Cas source code:

    public final boolean compareAndSet(int expect, int update) {
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
    }

2. Go inside compareAndSwapInt and find that the method is modified by native;

	...//Other codes
  	public native void throwException(Throwable var1);

    public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);

    public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

    public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);
    ...//Other codes

3.1 Unsafe

Is the core class of CAS. Since Java methods cannot directly access the underlying system, they need to be accessed through local methods. Unsafe is equivalent to a back door based on this
Class can directly manipulate data in a specific memory. Unsafe class exists in sun In misc package, its internal method operation can directly operate memory like C pointer, because the execution of CAS operation in Java depends on the method of unsafe class.
Note: all methods in the Unsafe class are modified native ly, that is, the methods in the Unsafe class directly call the underlying resources of the operating system to perform corresponding tasks

3.2. Variable valueOffset

Indicates the offset address of the variable value in memory, because Unsafe obtains data according to the memory offset address.

	/**
	* Atomically increments by one the current value .
	* @return the previous value
	* */
	public final int getAndIncrement() {
		return unsafe.getAndAddInt(this, valueOffse, 1);
	}

3.3. The variable value is modified with volatile to ensure the memory visibility between multiple threads.

Detailed comparison principle:

	...//Other codes
    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;
    }
    ...//Other codes

Why does AtomicInteger use Cas instead of synchronized?

Synchronized allows only one thread to run (synchronized principle). Although consistency is guaranteed, concurrency is reduced. The bottom layer of cas is unsafe and unlocked to ensure consistency. Multiple threads are allowed to operate at the same time, and concurrency is guaranteed, but there are many loops.
Reference link:

https://www.bilibili.com/video/BV1zb411M7NQ?p=13&spm_id_from=pageDriver

Topics: Java Back-end