转载

从AtomicInteger到AQS原理

  1. AtomicIntger是对int类型的一个封装,它提供了原子自增方法、原子自减方法以及原子赋值方法,即提供原子性的访问和更新操作。其中volatile保证了内存可见性(volatile这里在 Java内存模型和volatile、synchronized 里面讲过,不了解的可以跳过去看看),其原子性操作的实现是基于CAS(compare-and-swap)技术。
  2. 所谓CAS,就是获取某个数值的标志位,存储下来,然后再利用CAS指令试图进行更新。如果当前标志位数值未变,代表没有其他线程进行并发修改这个数值,则成功更新。否则,可能出现不同的选择,要么进行重试,要么就返回一个成功或者失败的结果。
  3. 从AtomicInteger的内部属性可以看出,它依赖于Unsafe提供的一些底层能力,进行底层操作;以volatile的value字段,记录数值,以保证可见性。
  4. CAS是Java并发中所谓lock-free机制的基础。

AQS

理解为什么需要AQS,如何使用AQS,至少要做什么,再进一步结合JDK源代码中的实践,理解AQS的原理与应用

什么是AQS

AQS是AbstactQueuedSynchronizer的简称,它是一个Java提高的底层同步工具类,用一个int类型的变量 --state 表示同步状态,并提供了一系列的CAS操作来管理这个同步状态。AQS的主要作用是为Java中的并发同步组件提供统一的底层支持,用法是通过继承AQS实现其模版方法,然后将子类作为同步组件的内部类。比如ReentrantLock里面的子类Sync:

public class ReentrantLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = 7373984872572414699L;
    private final Sync sync;

    abstract static class Sync extends AbstractQueuedSynchronizer {
        ...
    }
}
复制代码

AQS内部数据和方法,可以简单拆分为:

  1. 一个volatile的整数成员表征状态,同时提供了setState和getState方法
private volatile int state;
复制代码
  1. 一个先入先出(FIFO)的等待线程队列,以实现多线程间竞争和等待,这是AQS机制的核心之一。
//内部类Node
static final class Node
复制代码
  1. 各种基于CAS的基础操作方法,以及各种期望具体同步结构去实现的acquire/release方法。
//基于CAS的基础操作方法
private final boolean compareAndSetHead(Node update) 
private final boolean compareAndSetTail(Node expect, Node update) 
private static final boolean compareAndSetWaitStatus(Node node,int expect,int update) 
private static final boolean compareAndSetNext(Node node, Node expect, Node update) 

//实现的acquire/release方法等等
public final void acquire(int arg) 
public final boolean release(int arg)
······
复制代码
  1. 要利用AQS实现一个同步结构,至少要实现两个基本类型的方法,分别是acquire操作,获取资源的独占权;还有就是release操作,释放对某个资源的独占。
原文  https://juejin.im/post/5d6a0675f265da03eb13e0cf
正文到此结束
Loading...