CAS principle

What is CAS

CAS (compareAndSwap), Chinese called comparative exchange, a non-atomic lock algorithm. Such processes are: it contains three parameters CAS (V, E, N), V represents the value of the variable to be updated, E represents an expected value, N represents the new value. Only when the value is equal to V E value, will set the value of V N, if the value of V and E values ​​are different, then the other threads have to do two updates, the current thread does nothing. Finally, CAS returns the current real value of V. Hold optimistic attitudes when CAS operation, it always believes he can successfully complete the operation.

CAS's full name Compare And Swap, literal translation is relatively exchange. Atomic instruction is a CPU, and its role is to allow the CPU compares the two values are equal, then the value of a location update atomically, which implementation is based on a hardware platform assembly instructions, the CPU of the intel used for is a cmpxchgcommand, that CAS is implemented by hardware, so as to enhance efficiency at the hardware level.

When multiple threads simultaneously using a CAS operating variables, only one will win, and successfully updated, and the rest will fail. Failure of the thread does not hang, only to be told that failed and allowed to try again, of course, also allows threads to achieve abort the operation. Based on this principle, CAS operating even if there is no lock, other threads can also be found to interfere with the current thread.

Compared with locks, use CAS will make the program look more complicated, but because of its non-blocking, it deadlock innate immunity, and the interaction between threads is very small. More importantly, the use of lock-free way to bring no lock contention overhead, there is no inter-thread scheduling overhead caused by frequent, so he has a better performance than lock-based approach.

Simply put, CAS requires you to give an additional expectations, that is, you think this variable should now look like. If the variable is not what you imagine, which indicates that it has been modified by someone else before. You will need to re-read, try to modify again just fine.

The underlying principle of CAS

So thanks to the development of hardware instruction set, in fact, we can use the synchronous operation of the two atoms become, but doing so does not make sense. So we can only rely on hardware to complete, from hardware to ensure a behavioral semantics it seems to require multiple operations by only a single processor instruction to complete. Such instructions are used:

1. Test and Set (Tetst-and-Set)

2. Obtain and increase (Fetch-and-Increment)

3. swap (Swap)

4. compare and swap (Compare-and-Swap)

The load-linked / storage conditions (Load-Linked / Store-Conditional)

 

CPU implement the atomic instruction in two ways:

1 by a bus locking to ensure atomicity.

Processors use a bus lock is actually the lock bus, called bus key is to use a LOCK # signal provided by the processor , this processor output when a signal on the bus, requesting other processors will be blocked live, then the process you can monopolize shared memory. However, this method costs too much. So had the following manner.

2 , by locking the cache to ensure atomicity.

The so-called cache memory area if the locking means is cached in the cache line processor, and is locked during the Lock operation, then when he executed the lock operation is written back to memory, the processor is not profess LOCK # signal on the bus, and when modify the internal memory address, and to allow him to guarantee cache coherency mechanism of the atomic operation, because the cache coherency mechanism will prevent more than two processors simultaneously modify the cache data memory area (and here is the same visibility principle volatile) when the other processor write-back data cache line is locked, it makes the cache line is invalid.

Note: There are two cases the processor does not use the cache locking.

1. When the operation data can not be cached within the processor, or the operation of a plurality of cache line of data across the processor bus lock calls.

2. Some processors do not support cache lock for the Intel 486 and Pentium processors, is to lock the memory bus is also called the region locked cache line processor.

 

For example CAS

CAS source analysis

under the category atomic JUC are achieved by the CAS, the following will be explained as an example to achieve AtomicInteger of CAS. as follows:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Unsafe是CAS的核心类,Java无法直接访问底层操作系统,而是通过本地(native)方法来访问。不过尽管如此,JVM还是开了一个后门:Unsafe,它提供了硬件级别的原子操作

 

 

 

 

 

 

 

内部调用unsafe的getAndAddInt方法,在getAndAddInt方法中主要是看compareAndSwapInt方法:

 

CAS可以保证一次的读-改-写操作是原子操作,在单处理器上该操作容易实现,但是在多处理器上实现就有点儿复杂了。

缓存加锁:其实针对于上面那种情况我们只需要保证在同一时刻对某个内存地址的操作是原子性的即可。缓存加锁就是缓存在内存区域的数据如果在加锁期间,当它执行锁操作写回内存时,处理器不在输出LOCK#信号,而是修改内部的内存地址,利用缓存一致性协议来保证原子性。缓存一致性机制可以保证同一个内存区域的数据仅能被一个处理器修改,也就是说当CPU1修改缓存行中的i时使用缓存锁定,那么CPU2就不能同时缓存了i的缓存行

CAS缺点

CAS虽然高效地解决了原子操作,但是还是存在一些缺陷的,主要表现在三个方法:循环时间太长、只能保证一个共享变量原子操作、ABA问题

 

循环时间太长

如果CAS一直不成功呢?这种情况绝对有可能发生,如果自旋CAS长时间地不成功,则会给CPU带来非常大的开销。在JUC中有些地方就限制了CAS自旋的次数,例如BlockingQueue的SynchronousQueue。

 

只能保证一个共享变量原子操作

看了CAS的实现就知道这只能针对一个共享变量,如果是多个共享变量就只能使用锁了,当然如果你有办法把多个变量整成一个变量,利用CAS也不错。例如读写锁中state的高地位

ABA问题

CAS需要检查操作值有没有发生改变,如果没有发生改变则更新。但是存在这样一种情况:如果一个值原来是A,变成了B,然后又变成了A,那么在CAS检查的时候会发现没有改变,但是实质上它已经发生了改变,这就是所谓的ABA问题。对于ABA问题其解决方案是加上版本号,即在每个变量都加上一个版本号,每次改变时加1,即A —> B —> A,变成1A —> 2B —> 3A。

 

Guess you like

Origin www.cnblogs.com/vycz/p/11946612.html