Wikipedia:
In computer science,Compare-and-swapCPU instruction ("CAS") (Or the compare & Exchange-cmpxchg instruction in the x86 and itanium ubuntures) is a special instruction that atomically (regarding intel X86, lock prefix shocould be there to make it really atomic) compares the contents of a memory location to a given value and, only if they are the same, modifies the contents of that memory location to a given new value. this guarantees that the new value is calculated based on up-to-date information; if the value had been updated by another thread in the meantime, the write wowould fail. the result of the operation must indicate whether it was med the substitution; this can be done either with a simple boolean response (this variant is often calledCompare-and-Set), Or by returning the value read from the memory location (NotThe value written to it ). compare-and-swap (and compare-and-Swap-double) has been an integral part of the IBM 370 (and all successor) ubuntures since 1970. the operating systems which run on these ubuntures make extensive use of compare-and-swap (and compare-and-Swap-double) to facilitate process (I. E ., system and user tasks) and processor (I. E ., central processors) parallelism while eliminating, to the greatest degree possible, the "disabled spin locks" which were employed in earlier IBM operating systems. in these operating systems, new units of work may be instantiated "Globally", into the global service priority list, or "locally", into the local service priority list, by the execution of a single Compare-and-swap instruction. this dramatically improved the responsiveness of these operating systems.
========================================================== ==============
Conclusion: CAS is a metadical language provided by the hardware CPU. Its principle is as follows: I think location V should contain the value A. if it contains the value, place location B. Otherwise, do not change this location. Just tell me the current value of this location.
The atomicxxx class in the Java concurrent library is based on the implementation of this metalanguage. Take atomicinteger as an example:
public final int incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
Among them, unsafe. compareandswapint () is an native method that calls the CAS metadage to complete this operation.
========================================================== ==============
Volatile.
According to the description in Java language specification, a main memory (main memory or Java heap memory) exists in the JVM system. All variables in Java are stored in the main memory, and all threads are shared.
Each thread has its own working memory (working memory). The working memory stores copies of some variables in the main memory. The thread operates on all variables in the working memory, threads cannot access each other directly, and variable transmission must be completed through primary storage.
Therefore, the value of the same variable may be different between the working memory and the primary storage. Volatile tells the processor not to put me into the working memory. Please operate on me directly in the main memory.
========================================================== ==============
Return to atomicinteger and notice the value declaration:
private volatile int value;
From the introduction of volatile, you can know that the assignment and read operations of volatile do not need to be locked. See the source code:
public final int get() {
return value;
}
public final void set(int newValue) {
value = newValue;
}
Note: Volatile does not work for double and long because JVM splits the value assignment or read operation on double or long into two 32-digit operations.
========================================================== ==============
So why does the auto-increment operation need to be completed through CAS? Observe the incrementandget () method carefully and find that the auto-increment operation is actually completed in two steps:
int current = get();
int next = current + 1;
Because valatile can only ensure that the latest value is read or written, the following situations may occur:
1. Thread a executes the get () operation and obtains the current value (assumed to be 1)
2. The B-thread executes the get () operation to obtain the current value (1)
3. Line B executes the next = Current + 1 operation, and next = 2.
4 A thread executes the next = Current + 1 operation, next = 2
This result is obviously not what we want. Therefore, CAS must be used for auto-increment operations.