JUC Learning (4) "Atomic Atomic Operation Class"

Preface

The concept of atomicity is a commonplace issue in multithreaded programming. The so-called atomicity means that one or more operations must be executed or not executed at all. There can be no partial success and partial failure.
In multithreading, if multiple threads update a shared variable at the same time, you may get an unexpected value. For example, i=1. The A thread updates i+1 and the B thread also updates i+1.
It is possible that the value of i is not equal to 3 after parallel operations by two threads. It may be equal to 2. Because A and B may both get 1 when updating variable i. This is a typical atomicity problem
. There are several ways to achieve atomicity in multithreading. One of them is to add a Synchronized lock.
Starting from JDK 1.5, the Atomic package is provided in the JUC package, which provides atomic operations on commonly used data structures. It provides a simple, efficient, and thread-safe way to update a variable

Atomic operation classes in JUC

Due to the relationship of variable types, 12 classes of atomic operations are provided in JUC. These 12 categories can be divided into four categories

  • Basic types of atomic updates
    1. AtomicBoolean
    2. AtomicInteger
    3. AtomicLong
  • Atomic update array
    1. AtomicIntegerArray
    2. AtomicLongArray
    3. AtomicReferenceArray
  • Atomic update quote
    1. AtomicReference
    2. AtomicReferenceFieldUpdater
    3. AtomicMarkableReference (update the reference type with mark bits)
  • Atomic update field
    1. AtomicIntegerFieldUpdater
    2. AtomicLongFieldUpdater
    3. AtomicStampedReference

AtomicInteger principle analysis

Analysis of atomicInteger main methods

  • getAndIncrement
public final int getAndIncrement() {
    
    
    return unsafe.getAndAddInt(this, valueOffset, 1);
}

getAndIncrement actually calls the method provided in the unsafe class. The
Unsafe class was mentioned earlier when we analyzed AQS. This class is equivalent to a backdoor, allowing Java to directly manipulate the memory space like a C language pointer. Of course, it also brings some drawbacks, that is, the problem of pointers. In fact, this class is used in many ways, in addition to the JUC package, there are Netty, kafka, etc.

This class provides many functions, including multi-thread synchronization (monitorEnter), CAS operation (compareAndSwap), thread suspension and recovery (park/unpark), memory barrier (loadFence/storeFence) memory management (memory allocation, memory release, acquisition Memory address, etc.)

  • valueOffset
private static final long valueOffset;

static {
    
    
    try {
    
    
        valueOffset = unsafe.objectFieldOffset
            (AtomicInteger.class.getDeclaredField("value"));
    } catch (Exception ex) {
    
     throw new Error(ex); }
}

Obtain the offset of the current Value in the memory through unsafe.objectFieldOffset(), and then obtain the value of value from the memory based on this offset to compare with the current value to achieve optimistic locking

  • getAndAdd jdk1.7 and jdk1.8 are implemented in different ways (getAndAddInt is a method in unsafe.class)
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;
}

Through the do/while loop, atomic increment based on CAS optimistic lock. In fact, the function of the previous valueOffset is to obtain the current value from the main memory and compare it with the expected value. If they are equal, increment the value and end the loop

  • get method
private volatile int value;

public final int get() {
    
    
    return value;
}

The get method only needs to directly return the value of value, where the value is modified by Volatile to ensure visibility


  • The implementation of other methods AtomicInteger is very simple, so we can quickly analyze its implementation principles, of course, in addition to the two methods just analyzed, there are other. For example, it provides compareAndSet, allowing clients to implement optimistic lock operations based on AtomicInteger
public final boolean compareAndSet(int expect, int update) {
    
    
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

Next
: "JUC Other Common Concurrency Tools" of JUC Learning (5)

Guess you like

Origin blog.csdn.net/nonage_bread/article/details/110933775