AQS

104 阅读2分钟

构建锁和同步器的一个框架。 重点信息:

  • 底层的数据结构?
  • 核心的方法?怎么实现的?
  • 获取方式:独占(公平和非公平)和共享、组合?

核心思想与数据结构

存在一个共享资源,一个线程来请求,如果资源此时空闲,那么将该线程设置为工作线程,并将资源设置为锁定状态,如果资源不空闲,那么需要一套阻塞线程以及唤醒后进行锁分配的机制(CLH队列)。

CLH队列——虚拟的双向队列,将每个请求共享资源的线程封装成一个队列中的节点实现锁的分配。

int变量——用来表示同步状态,使用CAS对该状态进行原子操作。 condition queue—— 条件队列(单向链表),只有当使用condition的时候才需要。

image.png

private volatile int state;//共享变量,使用volatile修饰保证线程可见性
//返回同步状态的当前值
protected final int getState() {  
        return state;
}
 // 设置同步状态的值
protected final void setState(int newState) { 
        state = newState;
}
//原子地(CAS操作)将同步状态值设置为给定值update如果当前同步状态的值等于expect(期望值)
protected final boolean compareAndSetState(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

共享方式

不同自定义同步器获取资源的方式也不一样。

自定义同步器只需要实现资源的获取与释放即可。 至于怎么维护等待队列(资源获取失败等待与唤醒),AQS在上层已经帮我们实现好了。

底层实现

采用模版方法

isHeldExclusively()//该线程是否正在独占资源。只有用到condition才需要去实现它。 tryAcquire(int)//独占方式。尝试获取资源,成功则返回true,失败则返回false。 tryRelease(int)//独占方式。尝试释放资源,成功则返回true,失败则返回false。 tryAcquireShared(int)//共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。 tryReleaseShared(int)//共享方式。尝试释放资源,成功则返回true,失败则返回false。

其中,对于独占锁,初使的state为0,第一个线程拿到后对state+1。释放的时候-1。