This is the fourth day of my participation in the August More text Challenge. For details, see:August is more challenging
Source code analysis
The underlying principles of CAS are based on spin operations and the Unsafe class
class MyTask2 {
static AtomicInteger num = new AtomicInteger(5);
public static void main(String[] args) { num.getAndIncrement(); }}Copy the code
Let’s look at the source code for the getAndIncrement method
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
/**
* Atomically increments by one the current value.
*
* @return the previous value
*/
public final int getAndIncrement(a) {
return unsafe.getAndAddInt(this, valueOffset, 1); }}Copy the code
You can see that the return is the getAndAddInt method called by the instance of the unsafe class
Among them
- This: current object
- ValueOffset: indicates the memory offset. The value for Unsafe is obtained based on the memory offset address
- 1: indicates the value increased each time
Clicking on the Unsafe class, we see that many of its methods are native modified, meaning that the methods in the Unsafe class call the underlying operating system resources directly to perform the response task
public native void park(boolean var1, long var2);
public native int getLoadAverage(double[] var1, int var2);
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
Let’s focus on the do while loop
- First var5 = this.getintvolatile (var1, var2); Var1 is the current variable and VAR2 is the memory offset
- While compareAndSwapInt tries to change the value of var5. This method gets the value of the pair of variables from VAR1 and var5. If the value is different from var5, another thread has changed the value at the address var1+var2. The number continues to loop.
- If this value is the same as var5, it is not modified by another thread. You can change the value at VAR1 + VAR2 to VAR5 + VAR4 and return true to exit the loop
Since compareAndSwapInt is an atomic operation, changing the value at var1+ VAR2 is thread safe.
You can see that you keep trying in the while loop without making a change. That’s the idea behind the lock implementation, which guarantees thread safety and concurrency compared to synchronized. Instead of locking a block of code and keeping other threads out, the thread keeps trying.
Unsafe
It’s the core class of CAS. Knowing that Java methods can’t access the underlying system and need to be accessed through native methods, the Unsafe class provides a backdoor to manipulating memory-specific data directly.
Let’s look at the location of the Unsafe class
package sun.misc;
public final class Unsafe {}Copy the code
You can see that it’s in the sum.misc package, and that the inner methods can directly manipulate memory like C Pointers, because the execution of CAS operations in Java depends on the Unsafe class’s methods
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
// setup to use Unsafe.compareAndSwapInt for updates
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw newError(ex); }}private volatile int value;
Copy the code
The value variable is volatile to ensure the visibility of data in multithreaded situations.
CAS, called compact-and-swap, is a CPU concurrency primitive that determines whether a value in a memory location is the expected value And, if so, changes it to a new value. The process is atomic
The CAS concurrency primitive is now the methods in the sun.misc.unsafe class in the JAVA language. Calling the CAS method in the UnSafe class, the JVM will implement the CAS assembly instruction for us. This is a completely hardware dependent operation through which atomic operations are implemented.
The primitive
As a system primitive, CAS belongs to the category of operating system language, and is composed of several instructions to complete a process of a function. The execution of the primitive must be continuous, and it is not allowed to be interrupted during the execution. In other words, CAS is an atomic instruction of THE CPU, which will not cause the problem of data inconsistency.