What are the disadvantages of 66-CAS?

CAS has many advantages. For example, it can avoid adding mutual exclusion locks and can improve the operating efficiency of the program. However, CAS also has very obvious shortcomings. Therefore, when we use CAS, we should also consider its advantages and disadvantages, and make reasonable technical selection.

Let's take a look at the main shortcomings of CAS.

ABA problem

First of all, the biggest disadvantage of CAS is the ABA problem.

The criterion for determining whether CAS performs swap is "whether the current value is consistent with the expected value". If they are the same, it is considered that the value has not changed during this period, which is not a problem in most cases.

But in some business scenarios, we want to know exactly whether this value has changed since the last time we saw this value . For example, suppose this value changes from A to B, and then from B to A. At this time, we not only think that it has changed, but also think that it has changed twice.

In this scenario, when we use CAS, we cannot see the two changes, because it is not enough to just judge whether the current value is consistent with the expected value. What CAS checks is not whether the value has changed, but to compare whether the current value and the expected value are equal. If the value of the variable changes from the old value A to the new value B and then back to the old value A, because the most The initial value A and the current value A are equal, so CAS will consider that the value of the variable has not changed during this period. Therefore, CAS cannot detect whether the value has been modified during this period, it can only check whether the present value is the same as the original value.

Let’s take an example: Suppose that the initial value obtained by the first thread is 100, and then the calculation is performed. In the process of calculation, a second thread changes the initial value to 200, and then there is a third thread to change the initial value. 200 changed back to 100. When the first thread finishes calculating to execute CAS, it will compare whether the current value is equal to the initial value 100 obtained at the beginning. At this time, it will find that it is indeed equal to 100, so the thread thinks that there is no value during this period. If it has been modified, it is of course necessary to change this 100 to the new value just calculated, but in fact, other threads have modified this value in the process, and ABA problems will occur .

If an ABA problem occurs, the thread will never know whether other threads have modified this value during the calculation process. Since the first thread finds that the current value and the expected value are equal, it will think that there is no value during this period. The thread has modified the value of the variable, so some of its next operation logic is processed according to the logic that the value has not been modified during this period . For example, it may print a log: "This modification is very smooth", but It should trigger other logic . For example, when it finds that other threads have modified this value during this period, it should actually print "This modification process was disturbed."

So how to solve this problem? Add a version number to solve it.

We add a version number in addition to the variable value itself, then the change path of this value changes from A→B→A to 1A→2B→3A , so that we can judge whether the value is by comparing the version number It has changed , it is more reliable than we directly compare whether the two values ​​are consistent, so through this kind of thinking, the ABA problem can be solved.

The AtomicStampedReference class is provided in the atomic package . It is specifically used to solve the ABA problem. The solution is to use the version number. AtomicStampedReference maintains a data structure similar to <Object,int>, where int is used for counting Yes, that is, the version number, it can perform atomic updates to this object and the int version number at the same time, thus solving the ABA problem. Because we judge whether it has been modified, it is no longer based on whether the value has changed, but whether the version number has changed. Even if the value is the same, their version numbers are different.

The above is an introduction to the first shortcoming of CAS-the ABA problem.

Spin time is too long

The second disadvantage of CAS is that the spin time is too long.

Since a single CAS may not be able to execute successfully, CAS is often implemented in conjunction with a loop , sometimes even in an endless loop, retrying continuously, until the thread competition is not fierce, the modification can be successful.

However, if our application scenario itself is a high-concurrency scenario, it may cause CAS to be unsuccessful all the time. In this case, the cycle time will become longer and longer . And during this period, CPU resources are also being consumed all the time, which will have a great impact on performance. So this requires us to choose whether to use CAS according to the actual situation. In high concurrency scenarios, the efficiency of CAS is usually not high.

Range cannot be controlled flexibly

The third disadvantage of CAS is that it cannot flexibly control the scope of thread safety.

Usually when we execute CAS, it is for one, not multiple shared variables. This variable may be of Integer type, or Long type, object type, etc., but we cannot perform CAS for multiple shared variables at the same time Operation, because these multiple variables are independent, simply combining atomic operations together does not have atomicity. Therefore, if we want to perform CAS operations on multiple objects at the same time and want to ensure thread safety, it is more difficult.

There is a solution, that is to use a new class to integrate the group of shared variables just now, the multiple member variables in this new class are just the multiple shared variables, and then use the AtomicReference in the atomic package. Perform the CAS operation on this new object as a whole, so that thread safety can be guaranteed.

In contrast, if we use other thread safety technologies, it may become very easy to adjust the scope of thread safety. For example, when we use the synchronized keyword, if we want to lock more code, we only need to change Put more code in the synchronous code block .

to sum up

The three shortcomings of CAS are the ABA problem, the excessively long spin time, and the range of thread safety cannot be flexibly controlled. After we understand its shortcomings, we can focus on technology selection.

Guess you like

Origin blog.csdn.net/Rinvay_Cui/article/details/111059186