The underlying implementation principle of CAS in Java concurrent programming

What is CAS?

The full name of CAS is Compare-And-Swap (the internal implementation of optimistic locking)

Function: Used to judge whether the Value value of a certain location in the memory is the expected value A, if it is, change to the new value B, the whole operation process is an atomic operation

scenes to be used:

CAS is embodied in the Java language that the various methods of the sun.misc.Unsafe class
call the CAS method in the UnSafe class. The JVM will help us realize the CAS assembly instruction, which is completely dependent on the hardware function, because CAS is a system primitive , The primitive belongs to the operating system use category, is composed of several instructions, used to complete a process of a certain function, and the execution of the primitive must be continuous, and it is not allowed to be interrupted during the execution, which means that CAS is A CPU atomic instruction will not cause the so-called data inconsistency problem


Namely: CAS is thread safe

Core attributes:

1. Unsafe core class

Since Java methods cannot directly access the underlying operating system, they need to be accessed through native methods. Unsafe is equivalent to a backdoor, based on which specific memory data can be directly manipulated. The Unsafe class exists in the sun.misc package, and its internal methods Operation can directly manipulate memory like C pointer

Because all methods of the Unsafe class are natively modified, they can directly call the underlying resources of the operating system to perform corresponding tasks. The reason why the Atomic modified packaging class can guarantee atomicity depends on the underlying unsafe class

2, valueOffset variable

Indicates the offset address of the variable value in the memory. Unsafe obtains the data according to the memory offset address. Through the valueOffset memory address, the value can be directly obtained, and then the operation is added.

3. The value of the volatile modified variable

Ensure memory visibility between multiple threads

During operation, you need to compare the value in the operation memory and compare it with the value in the main memory

If the comparison of Value value and expected value A returns false, then the while method is executed until the expected value is the same as the memory value Value

Synchronized is not used at the bottom layer, but CAS is used to improve concurrency, and at the same time, to achieve consistency, because after each thread comes in, it enters the do while loop, and then continuously obtains the value in the memory. It is necessary to judge whether Is the latest, and then update operation.

example:

假设线程A和线程B同时执行修改操作

1. value原始值为10,此时,线程A和线程B各自持有一份值为10的副本,分别存储在各自的工作内存
2. 当线程A拿到value值10的时候,CPU进行切换,线程A被挂起(失去CPU执行权)
3. 线程B也拿到Value值10,线程B并没有被挂起,接着执行了CAS方法,通过比较内存值正好为10,则表示成功,接着对内存值进行修改为15,至此,线程B修改操作完成
4. 之后线程A恢复,执行CAS方法,通过比较,发现自己副本获取到的值10和主内存中的数字15不一致,说明内存值已经被其它线程抢先一步修改,进而导致A线程本次修改失败,只能通过执行do while重新读取内存值后再进行CAS,因为内存值value被volatile修饰,所以其它线程对它的修改,线程A总能够看到,线程A继续执行compareAndSwapInt进行比较替换,直到成功。

This involves a spin idea, if the operation returns false, spin until the operation returns true

CAS disadvantages

1. High CPU overhead

     If under high concurrency, many threads need to update a variable, and the update is unsuccessful for many times, and because CAS is a spin operation, repeated loops, resulting in too long time, excessive consumption, and a lot of pressure on the cpu. In the worst case, the value obtained by a thread is different from the expected value, so it will loop indefinitely


2. CAS can only guarantee variable-level atomicity, not the atomicity of code blocks

     When performing operations on a shared variable, the atomic operation can be guaranteed by looping CAS, but for multiple shared variable operations, looping CAS cannot guarantee the atomicity of the operation. At this time, only locks can be used to ensure atomicity.

 

3. ABA problem
     CAS will have ABA problems in multi-threaded scenarios

   example:

线程A,期望值为10,欲更新的值为15
线程B,期望值为10,欲更新的值为15
     
场景:
    1.线程A抢先获得CPU时间片,而线程B因为其他原因阻塞
    2.线程A取值与期望的值10比较,发现相等然后将值更新为15
    3.这个时候出现了线程C,期望值为15,欲更新的值为10,线程C取值与期望的值15比较,发现相等则将值更新为10
    4.此时线程B从阻塞中恢复过来,并且获得了CPU时间片,这时候线程B取值与期望的值10比较,发现相等则将值更新为15
    虽然线程B也完成了操作,但是线程B并不知道这个值已经经过了10->15->10的变化过程。

 

    Solution:
    add the version number in front of the variable, the version number of the variable is +1 each time the variable is updated, that is, A->B->A becomes 1A->2B->3A

to sum up:

CAS (compareAndSwap)

By comparing whether the current working memory value and the main physical memory value are equal, if it returns true, perform the specified operation, return false, then continue the spin comparison until the values ​​of the main memory and the working memory are consistent

Guess you like

Origin blog.csdn.net/weixin_43562937/article/details/107180533