JUC下的原子类实现原理

volatile不能解决num++这类复合类操作的原子性问题,相比锁机制,使用原子类更精巧。

悲观的解决方案(阻塞同步):

            num++操作,1.读取 2. 加一  3. 写入 三步组成的,就是复合类的操作,在并发环境下,如果不做不做何人同步处理,就会有线程安全问题。最直接的处理方式就是加锁。

synchronized(this) {
    num++;
}

      使用独占锁机制来解决,是一种悲观的并发策略。每次操作数据时都认为别的线程会参与竞争修改,所以直接加锁。同一时刻只能用一个线程持有锁,那其他线程就会阻塞。线程的挂起和恢复会带来很大的性能开销。

乐观的解决策略:

          就是每次操作数据的时候,都认为别的线程不会参与竞争修改,也不加锁。如果操作成功了那最好;如果失败了,如中途有别的线程进入并修改了数据,也不会阻塞,一般采用反复尝试的策略。

如AtomicInteger原子类

private volatile int value;  //volatile保证可见性

public final int incrementAndGet() {
        for (;;) {
            int current = get();
            int next = current + 1;
            if (compareAndSet(current, next))   //CAS保证原子性
                return next;
        }
    }

 public final boolean compareAndSet(int expect, int update) {
    return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
 } 

incrementAndGet的逻辑:

  1. 先获取当前的value值

   2.  对value加一

   3.  第三步时关键,调用comparaAndSet方法来进行原子更新操作,语义是:

         先检查当前value是否等于current,如果相等,则意味着value没被其他线程修改过,更新并返回true,如果不相等,compareAndSet则会返回false,然后继续尝试更新。其实就是CAS算法

CAS  +  volatile

猜你喜欢

转载自blog.csdn.net/weixin_39590058/article/details/87873121
今日推荐