Atomic variables and non blocking synchronization in concurrent Java programming
- 2020-04-01 03:49:01
- OfStack
1. Non-blocking algorithm
Non-blocking algorithms are concurrent algorithms that can safely derive their threads, not through locking, but through low-level atomic hardware native forms such as comparison and exchange. Non-blocking algorithms are extremely difficult to design and implement, but they provide better throughput and better defense against survival problems such as deadlocks and priority reversals. Replace locks with the underlying atomized machine instructions, such as compare and swap (CAS,compare-and-swap).
Pessimistic technology
An exclusive lock is a pessimistic technique that assumes the worst (if left unlocked, other threads will destroy object state) and protects object state with a lock even if the worst does not happen.
Optimistic techniques
Update first, if a conflict occurs, give up the update and retry, otherwise the update succeeds.
4. The CAS operation
CAS has three operands, the memory value V, the old expected value A, and the new value B to be modified. If and only if the expected value A and memory value V are the same, change the memory value V to B, otherwise do nothing. The typical usage pattern of CAS is to first read A from V and calculate the new value B based on A, and then atomically change the value in V from A to B through CAS (as long as no thread changes the value of V to any other value during this period).
Listing 3. Code that illustrates the behavior (not the performance) of comparing and exchanging
public class SimulatedCAS {
private int value;
public synchronized int getValue() { return value; }
public synchronized int compareAndSwap(int expectedValue, int newValue) {
int oldValue = value;
if (value == expectedValue)
value = newValue;
return oldValue;
}
}
Listing 4. Implement the counter using compare and swap
public class CasCounter {
private SimulatedCAS value;
public int getValue() {
return value.getValue();
}
public int increment() {
int oldValue = value.getValue();
while (value.compareAndSwap(oldValue, oldValue + 1) != oldValue)
oldValue = value.getValue();
return oldValue + 1;
}
}
5. Atomic variables
Atomic variables support atomic update operations without lock protection, and the underlying implementation is CAS. There are 12 atomic variables, which can be divided into four groups: scalar class, updater class, array class, and composite variable class. The most common atomic variables are the scalar classes: AtomicInteger, AtomicLong, AtomicBoolean, and AtomicReference. CAS is supported for all types.
6. Performance comparison: locks versus atomic variables
Under the medium and low degree of competition, atomic variables can provide high scalability, and the performance of atomic variables is better than that of locks. But under the high intensity competition, the lock can avoid the competition more effectively, the performance of the lock will exceed the performance of the atomic variable. But in a more realistic scenario, the performance of atomic variables would exceed that of locks.