1. CAS principle
Chinese called comparative exchange --- the Compare And Swap
CAS (V, E, N)
V represents the value to be updated;
E represents the expected value;
N represents the new value.
Compare principle: When the values of V and E, N only then assigned to V; if V and E are not equal abandon the changes; re-read, try to modify again.
1.1 How to ensure atomicity
Atomicity assembly instructions based hardware, using CPU instructions to ensure atomicity;
// Unsafe 后门类,用于直接操作内存中的数据
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
private volatile int value;
/**
* CAS实现
*/
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
/**
* 使用自旋的方式保证线程安全
*/
public final int getAndUpdate(IntUnaryOperator updateFunction) {
int prev, next;
do {
prev = get();
next = updateFunction.applyAsInt(prev);
} while (!compareAndSet(prev, next));
return prev;
}
The drawback 1.2 CAS
Cycle time is too long
Some classes limit the number of spins
Atomic operation can only guarantee a shared variable
ABA problem
If a value is A, it became a B, and then turned into A, then check the CAS will find the time did not change, but in essence it has changed, which is called the ABA problem.
Use class AtomicStampedReference to solve the ABA problem.
If the current reference is == to the expected value, and the current flag value == the expected value of the flag, the flag will be current references and the current value assigned to the updated value.
/**
* CAS实现
*
* @param expectedReference 引用的预期值
* @param newReference 引用的新值
* @param expectedStamp 标志的预期值
* @param newStamp 标志的新值
*/
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) ||
casPair(current, Pair.of(newReference, newStamp)));
}
2. AQS principle
The acronym AQS ---- AbstractQueuedSynchronizer
Subclass defined as non-public internal helper class (private inner class inherits AQS); write lock when a helper, provides a template function is to acquire the lock and release the lock.
acquire (int arg) Acquires in exclusive mode, ignoring interrupts.
acquireShared (int arg) Acquires in shared mode, ignoring interrupts.
tryAcquire (arg) Attempts to acquire in exclusive mode state.
tryAcquireShared (int arg) Attempts to acquire in shared mode state
release (int arg) release in exclusive mode.
releaseShared (int arg) release in shared mode