CAS operation and implementation principle in Java

1. What is CAS?

CAS: Compare and Swap, translated to compare and exchange.

See this definition, we can say without any sense of the word, but the word does best summed up the process of CAS operations.

CAS operation includes three operands - a memory location (V), is expected to original value (A) and the new value (B). If the memory location of the original value matches the expected value, then the processor will automatically update the location value to the new value. Otherwise, the processor does nothing. In either case, it returns the value of the position before the CAS instruction. (In some special cases will be returned only if CAS CAS is successful, without extracting the current value.) CAS effectively explains, "I think the location should contain the value V A; If you include this value, the B put in this position; otherwise, do not change the location, just tell me the value of this location can now. "

The following this JAVA code, basically reflects the CAS process operation. Note, however, the real CAS operations are done by the CPU, the CPU will ensure atomicity operation, function is far from CAS JAVA code that can be realized (we shall see CAS assembly code).

	/**
	* 假设这段代码是原子性的,那么CAS其实就是这样一个过程
	*/
	public boolean compareAndSwap(int v,int a,int b) {
		if (v == a) {
			v = b;
			return true;
		}else {
			return false;
		}
	}

CAS generally synchronized manner for V read from address value A, the multi-step calculation performed to obtain a new value of B, then the value of V CAS from A to B. If the value of V has not been changed at the same time, the CAS operation was successful.

These words mean, CAS operation can prevent memory shared variable appears dirty dirty read write problem, the problem of multi-core CPU often in the case of multi-threaded, usually we use locks to avoid this problem, but to avoid the CAS operation multi-threaded lock contention, context switching, and process scheduling.

Similar to the CAS instruction allows the algorithm to perform a read - modify - write operations, without fear of other threads modify variables, because if another thread to modify variables, CAS will detect it (and failed), the algorithm can recalculate the operation.

CAS operations in the realization of the principle of 2.JAVA

CAS by calling JNI code implementation. JNI: Java Native Interface for the JAVA local calls, allow java to call other languages.

In compareAndSwapInt Unsafe class () method is an example, compareAndSwapInt is C and assembly code means to achieve.
The following from the analysis of the more common CPU (intel x86) to explain the realization of the principle of CAS.
Below is the source code in sun.misc.Unsafe compareAndSwapInt JDK classes () method:

// native方法,是没有其Java代码实现的,而是需要依靠JDK和JVM的实现
public final native boolean compareAndSwapInt(Object o, long offset,
                                              int expected,
                                              int x);

We can see this is a local method. c ++ code for this local approach openjdk in turn calls for: unsafe.cpp, atomic.cpp and atomicwindowsx86.inline.hpp. This ultimately the native method in a position of openjdk: openjdk-7-fcs-src-b147-27jun2011 \ openjdk \ hotspot \ src \ oscpu \ windowsx86 \ vm \ atomicwindowsx86.inline.hpp (corresponding to the windows operating system, X86 instruction set). Below is the source code fragment corresponding to the intel x86 processor:

// Adding a lock prefix to an instruction on MP machine
// VC++ doesn't like the lock prefix to be on a single line
// so we can't insert a label after the lock prefix.
// By emitting a lock prefix, we can define a label after it.
#define LOCK_IF_MP(mp) __asm cmp mp, 0  \
                       __asm je L0      \
                       __asm _emit 0xF0 \
                       __asm L0:

inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) 
{
  // alternative for InterlockedCompareExchange
  int mp = os::is_MP();
  __asm {
    mov edx, dest
    mov ecx, exchange_value
    mov eax, compare_value
    LOCK_IF_MP(mp)               // 这里需要先进行判断是否为多核处理器
    cmpxchg dword ptr [edx], ecx // 如果是多核处理器就会在这行指令前加Lock标记
  }
}

os::is_MP() Returns the current JVM is running on the machine whether the multi-core CPU, of course, return 1 for true, 0 for false

Followed by a period of inline assembler, C / C ++ inline assembly support, we know that this feature is like, I'll explain this in plain compilation of the general meaning.

  __asm {
    mov edx, dest             # 取Atomic::cmpxchg方法的参数dest内存地址存入寄存器edx
    mov ecx, exchange_value   # 取Atomic::cmpxchg方法的参数exchange_value内存地址存入寄存器ecx
    mov eax, compare_value    # 取Atomic::cmpxchg方法的参数compare_value内存地存入寄存器eax
    LOCK_IF_MP(mp)            # 如果是多核处理器,就在下一行汇编代码前加上lock前缀
    cmpxchg dword ptr [edx], ecx # 比较ecx和eax的中内存地址的中存的变量值,如果相等就写入edx内存地址中,否则不
  }

x86 assembler instruction cmpxchg itself ensures atomicity, in fact, is the realization of CAS operations cpu, so the question is, why guarantee the atomicity also need to add the prefix lock in multi-core processor in it?

The answer is: multi-core processors can not guarantee the visibility, lock prefix can ensure the visibility of this line compilation of all the values, the cause of this problem is caused by multi-core CPU cache (x86 culprit is the presence in the store buffer).
Such protection by the lock prefix visibility multicore processors, then the CPU to complete the operation by atomic CAS cmpxchg instruction perfect problem!
Say one more thing, this is only in x86 implementations for other platforms, there are different ways to achieve this hope that readers must be clear.
This assembly code read does not matter, but the effect that the lock mechanism uses the CPU to ensure that the entire CAS atomic operation. Atomic atomic operation on the operation --CPU locking mechanism and the CPU in the CPU.

3.concurrent CAS application package

Since the java CAS has both volatile and volatile read-write memory semantics, the communication between Java threads now have the following four ways:
. 1, thread A write volatile variables, then thread B reads the volatile variables.
2, A thread write volatile variable, then B CAS update this thread with volatile variables.
3, A thread with a volatile variable CAS updates, then updates the thread B with CAS volatile variables.
4, A thread with a volatile variable CAS updates, then thread B reads the volatile variables.

Note: volatile keyword to ensure the visibility of variables, based on JAVA memory model, each thread has its own stack memory, stack memory variables in different threads is possible because different operations within the stack, while the CPU is directly data manipulation stack and stored in its cache, so the emergence of multi-core CPU big problem, and that volatile variables ensure that each CPU core and the cache will not read data from the stack memory, but directly read data from the heap memory, and writes directly written back to the memory heap, thus ensuring the visibility and order among the local multi-threaded shared variables (but does not guarantee atomicity), on volatile - Java concurrent programming: volatile keyword analysis

Java operation of CAS can be implemented on a modern CPU hardware-level atomic instructions (JVM instead of relying on the operating system or locking mechanism), while the volatile keyword and ensures the visibility and instructions in the order of variables shared among threads, so by virtue of this two means, can be achieved without relying on the operating system to achieve locking mechanism to ensure the consistency of shared variables concurrent.

If we carefully analyze the source code implementation concurrent package, you will find a common realization mode:
First, declare shared variables to be volatile;
then, use of atomic CAS update conditions to achieve synchronization between threads;
at the same time, cooperate to the volatile read / write and read and write CAS has volatile memory semantics for communication between threads.

Here Insert Picture Description

Published 451 original articles · won praise 17 · views 10000 +

Guess you like

Origin blog.csdn.net/zt2650693774/article/details/105038214