AtomicInteger的CAS原理

一、乐观锁
乐观锁的核心思想:每次不加锁,而是假设没有冲突而去完成某项操作,如果因为冲突失败就去重试,直到成功为止。所以,当数据争用不严重时,乐观锁效果更好。比如CAS就是一种乐观锁思想的应用。

二、Java中CAS的实现
CAS就是Compare And Swap的意思。CAS是项乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。CAS有3个操作数,内存值V、旧的预期值A和要修改的新值B,当且仅当预期值A和内存值V相同时,将内存值V改为B,否则什么也不做。

三、AtomicInteger的实现
AtomicInteger是一个支持原子操作的Integer类,就是保证对AtomicInteger类型变量的增加和减少操作是原子性的,不会出现多个线程下的数据不一致问题。如果不使用AtomicInteger,要实现一个按顺序获取的ID,就必须在每次获取时进行加锁操作,以避免出现并发时获取到同样的ID的现象。
首先看incrementAndGet()方法,下面是具体的代码:
public final int incrementAndGet() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return next;
    }
 }
通过源码,可以知道,这个方法的做法为先获取当前的value属性值,然后将value加1,赋给一个局部的next变量,然而,这两步都是非线程安全的,但是整体是一个死循环,不断去做compareAndSet操作,直到成功为止,也就是说,修改的根本在compareAndSet方法里面,compareAndSet方法的代码如下:
public final boolean compareAndSet(int expect, int update) {
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
 }
compareAndSet方法调用的compareAndSwapInt()方法的声明如下,是一个native方法:
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, intvar5);
compareAndSet传入的为执行方法时获取到的value属性值,next为加1后的值,compareAndSet所做的为调用unsafe的 compareAndSwapInt方法来完成,此方法为native方法,compareAndSwapInt基于的是CPU的CAS指令来实现的,所以基于CAS的操作可认为是无阻塞的,一个线程的失败或挂起不会引起其它线程也失败或挂起。并且由于CAS操作是CPU原语,所以性能比较好。类似的,还有decrementAndGet方法,它和incrementAndGet()的区别是将 value 减1,赋值给next变量。
AtomicInteger中还有getAndIncrement和getAndDecrement方法,他们的实现原理和上面的两个方法完全相同,区别是返回值不同,前两个方法返回的是改变之后的值,即next。而这两个方法返回的是改变之前的值,即current。还有很多的其他方法,就不列举了。


猜你喜欢

转载自www.cnblogs.com/yuanfei1110111/p/10366847.html
今日推荐