CAS
1. Introduction to CAS
The full name of CAS Compare And Swap
, compare and exchange. It is an atomic instruction of the CPU, and the bottom layer is implemented based on the assembly instructions in the hardware. The CAS algorithm involves 3 operands 内存值V
, 预期原值A
, 新值B
, when the memory value V is equal to the expected value A, update the memory value V to the new value B.
CAS example:
For example: For i = 0 , i++
the application of CAS ideas, the thread reads the value of i 0 into the memory, and the original value A=0 is expected.
If V is equal to A, it means that there are no other threads performing i++
operations , so modify V to the new value B, which is 1;
If V is not equal to A, it means that other threads modify the value of i, and there is a concurrency security problem. Give up this modification and try again.
CAS operations are atomic. When multiple threads use CAS to modify data concurrently, there is no need to lock.
2. Problems with CAS
2.1 ABA problem
CAS is to check whether the expected original value A has changed. If the expected original value A is changed to another value C and then modified back to A, the thread will perform CAS comparison and find that the expected original value A has not changed, but has actually changed. .
The essence of the ABA problem is that CAS only checks the initial and final, and does not care about the change of the intermediate state
Why Solve ABA Problems
Assume a scenario: Xiao Ming has 100 yuan in his account and is going to withdraw 50 yuan. In the case of concurrent multi-threading, thread A and thread B both check the balance to be 100. Thread A successfully withdraws 50. Under normal circumstances, thread B should fail, but this If Xiao Ming's account receives 50 yuan, then thread B will succeed when using CAS for comparison, and another 50 yuan will be deducted. The result is that Xiao Ming withdraws 50 but deducts 100 yuan.
Solutions to ABA Problems
Use the version number to identify the state of the variable. For example, if A1 is changed to C2 and then changed back to A3, the ABA problem is solved if A1 and A3 are not equal.
Using AtomicStampedReference
classes to solve ABA problems
public class AtomicStampedReference<V> {
private static class Pair<T> {
final T reference; // 对象引用
final int stamp; // 用于标志版本号
private Pair(T reference, int stamp) {
this.reference = reference;
this.stamp = stamp;
}
static <T> Pair<T> of(T reference, int stamp) {
return new Pair<T>(reference, stamp);
}
}
/ **
* ......
*/
// pair使用volatile保证可见性
private volatile Pair<V> pair;
public boolean compareAndSet(V expectedReference, // 更新前的值
V newReference, // 更新后的值
int expectedStamp, // 预期的版本号
int newStamp) {
//更新后的版本号
// 获取当前元素值 + 版本号
Pair<V> current = pair;
return
expectedReference == current.reference && // 比较引用
expectedStamp == current.stamp && // 比较版本号
((newReference == current.reference && // 新引用等于旧引用
newStamp == current.stamp) || // 新版本号等于旧版本号
// 创建新的pair对象并CAS更新
casPair(current, Pair.of(newReference, newStamp)));
}
}
compareAndSet方法
Results of the:
- If the element value and version number have not changed and are the same as the new one, it means it has
CAS
been updated and returnstrue
- If the element value and version number have not changed and are different from the new one, create a new one
Pair
and initialize it to the new value and version number - other return
false
2.2 Only one atomic operation of a shared variable can be guaranteed
When the CAS operation is performed on multiple shared variables, the atomicity of the operation cannot be guaranteed, such as the operation on two or more variables and the operation on the code block.
solution
Java1.5
Finally, a class JDK
is provided AtomicReference
to ensure the atomicity between referenced objects, and multiple variables can be placed in one object for atomic operations.
synchronized
You can choose to use or lock for code blocks Lock
.
2.3 Long cycle time and high overhead
CAS
Generally, loop operations are used to continuously retry (such as spin locks). If the time is long, the overhead of CPU resources will be increased.
Optimization
You can set the number of spins, the default is 10 times. JVM
Provides adaptive spin locks, automatically adjusts the number of cycles, and can determine whether to use the number of times or not CAS
according to the previous CAS
execution of the same lockCAS
CAS