Understand CAS and AQS in one article

JAVA multithreading, something interviewers like to ask

Some conceptual stuff

Atomicity means that the operation is indivisible. Regardless of whether it is multi-core or single-core, an atomic quantity, only one thread can operate on it at a time. In short, operations that are not interrupted by the thread scheduler during the entire operation can be considered atomic. For example, a = 1;

Non-atomicity: This means that the thread scheduler will interrupt the operation during the entire process. Operations
like "a ++" are not atomic, because it may have to go through the following two steps:

(1) Take the value of a

(2) Calculate a+1

If there are two threads t1, t2 are performing such operations. After the first step, t1 was interrupted by the thread scheduler before it had time to add 1, so t2 began to execute. After t2 was executed, t1 began to execute the second step (at this time, the value of a in t1 may still be the old value, It is not certain, it will only appear if the value of a in thread t2 is not updated to t1 in time). An error occurred at this time, and the operation of t2 is equivalent to being ignored

JAVA thread scheduling-preemptive scheduling (priority)


CAS—(Compare And Swap) compare and exchange

Adopt optimistic locking thinking-always think that you can complete the operation

When multiple threads manipulate a variable, only one thread will update successfully, the others fail, and the failed thread is allowed to retry

CAS spin waiting

Locks or synchronizedcan be achieved keyword atomic operation, so why use CAS, because the locking or synchronized keyword performance brought great loss, but with the CAS optimistic locking can be achieved, it is actually the direct use of the CPU Level instructions, so the performance is very high.

So how does CAS realize the spin lock? CAS uses CPU instructions to ensure the atomicity of the operation to achieve the lock effect. As for the spin, it is generally realized with an infinite loop. In this way, in an infinite loop, a CAS operation is executed. When the operation succeeds and returns true, the loop ends; when it returns false, the loop continues, and the CAS operation continues to be tried until it returns true.

Enter the CAS source code to see
import java.util.concurrent.atomic.AtomicInteger;

Atomically set the value to the given updated value ( update), if the current value is equal to the expected value ( expect). Return true, update the value of the variable, the actual value is not equal to the expected value, return false, the thread does nothing, CAS returns the current variable value;

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

Inside unsafe.compareAndSwapInt(this, valueOffset, expect, update);it is a nativemethod, using c ++ implementation, are interested can go and see safe.cpp JDK source code files, CAS operates directly with the operating system;

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);
ABA problem caused by CAS

What is ABA?

I can know from the above that there is an important prerequisite for the implementation of the CAS algorithm: you need to take out the data at a certain moment in the memory, and then compare and replace it at the next moment. At this time difference, the data may have changed, which leads to the ABA problem;

Solution: Part of it is solved by adding the version number (version),

AQS is an abstract queue synchronizer

AQS maintains a shared resource variable state with volatile semantics (supporting visibility under multiple threads) and a FIFO thread waiting queue (when multithreaded competition state is blocked, it will enter this queue). java.util.concurrent.locks.AbstractQueuedSynchronizerAbstract class, referred to as AQS

img

The way AQS shares resources: exclusive and shared

AQS provided by default and shared exclusive modes, with a corresponding implementation JDK ReentrantLockandReentrantReadWriteLock

Exclusive: Only one thread can execute, the specific JAVA implementation has ReentrantLock

Shared: multiple threads execute at the same time

AQS is implemented based on volitale and CAS. A valitale type variable state is maintained in AQS to
make a reentrant number of reentrant locks. Locking and releasing locks are also carried out around this variable.

Insert picture description here

Recommended AQS analysis


Guess you like

Origin blog.csdn.net/weixin_44313584/article/details/114695205