AbstractQueuedSynchronizer 详解
Posted loveer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AbstractQueuedSynchronizer 详解相关的知识,希望对你有一定的参考价值。
package java.util.concurrent.locks;
基本介绍
AbstractQueuedSynchronizer(队列同步器)可以看作是并发包(java.util.concurrent)的基础框架。
AQS是一个抽象类,当构建一个同步组件的时候,需要定义一个子类继承AQS,应用了模板方法设计模式
模板模式由一个抽象类和一个实现类组成,抽象类中主要有三类方法:
模板方法:实现了算法主体框架,供外部调用。里面会调用原语操作和钩子操作。
原语操作:即定义的抽象方法,子类必须重写。
钩子操作:和原语操作类似,也是供子类重写的,
区别是钩子操作子类可以选择重写也可以选择不重写,如果不重写则使用抽象类默认操作,通常是一个空操作或抛出异常。
AQS中可供子类重写的钩子操作
方法名称 | 描述 |
---|---|
boolean tryAcquire(int arg) | 独占式获取同步状态,成功返回true,失败返回false。 |
boolean tryRelease(int arg) | 独占式释放同步状态,成功返回true,失败返回false。 |
int tryAcquireShared(int arg) | 共享式获取同步状态,获取成功则返回值>=0 |
boolean tryReleaseShared(int arg) | 共享式释放同步状态,成功返回true,失败返回false。 |
boolean isHeldExclusively() | 判断同步器是否在独占模式下被占用,一般用来表示同步器是否被当前线程占用 |
模板方法
子类重写相关钩子操作后,AQS中提供的模板方法才能正常调用
方法 | 描述 |
---|---|
void acquire(int arg) | 独占式获取同步状态,该方法会调用子类重写的tryAcquire(int arg),如果tryAcquire返回true则该方法直接返回,否则先将当前线程加入同步队列的尾部,然后阻塞当前线程 |
void acquireInterruptibly(int arg) | 和acquire类似,只是当线程获取同步状态失败被阻塞后,可以响应中断,收到中断后将会取消获取同步状态 |
boolean tryAcquireNanos(int arg, long nanosTimeout) | 在acquireInterruptibly的基础上加了超时限制,如果在超时时间内获取到同步状态返回true,否则返回false |
boolean release(int arg) | 独占式释放同步状态,该方法会在释放同步状态后将第一个节点(对应刚刚释放同步状态的线程)的后继节点对应的线程唤醒。 |
void acquireShared(int arg) | 共享式获取同步状态,该方法会调用子类重写的tryAcquireShared(int arg),如果tryAcquireShared返回true则该方法直接返回,否则先将当前线程加入同步队列的尾部,然后阻塞当前线程 |
void acquireSharedInterruptibly(int arg) | 和acquireShared类似,只是当线程获取同步状态失败被阻塞后,可以响应中断,收到中断后将会取消获取同步状态 |
boolean tryAcquireSharedNanos(int arg, long nanosTimeout) | 在acquireSharedInterruptibly的基础上加了超时限制,如果在超时时间内获取到同步状态返回true,否则返回false |
boolean releaseShared(int arg) | 共享式的释放同步状态 |
源码分析
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable
private static final long serialVersionUID = 7373984972572414691L;
protected AbstractQueuedSynchronizer()
static final class Node
static final Node SHARED = new Node();
static final Node EXCLUSIVE = null;
static final int CANCELLED = 1;
static final int SIGNAL = -1;
static final int CONDITION = -2;
static final int PROPAGATE = -3;
volatile int waitStatus;
volatile Node prev;
volatile Node next;
volatile Thread thread;
Node nextWaiter;
final boolean isShared()
return nextWaiter == SHARED;
final Node predecessor()
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
Node()
Node(Node nextWaiter)
this.nextWaiter = nextWaiter;
THREAD.set(this, Thread.currentThread());
Node(int waitStatus)
WAITSTATUS.set(this, waitStatus);
THREAD.set(this, Thread.currentThread());
final boolean compareAndSetWaitStatus(int expect, int update)
return WAITSTATUS.compareAndSet(this, expect, update);
final boolean compareAndSetNext(Node expect, Node update)
return NEXT.compareAndSet(this, expect, update);
final void setPrevRelaxed(Node p)
PREV.set(this, p);
private static final VarHandle NEXT;
private static final VarHandle PREV;
private static final VarHandle THREAD;
private static final VarHandle WAITSTATUS;
static
try
MethodHandles.Lookup l = MethodHandles.lookup();
NEXT = l.findVarHandle(Node.class, "next", Node.class);
PREV = l.findVarHandle(Node.class, "prev", Node.class);
THREAD = l.findVarHandle(Node.class, "thread", Thread.class);
WAITSTATUS = l.findVarHandle(Node.class, "waitStatus", int.class);
catch (ReflectiveOperationException e)
throw new ExceptionInInitializerError(e);
private transient volatile Node head;
private transient volatile Node tail;
private volatile int state;
protected final int getState()
return state;
protected final void setState(int newState)
state = newState;
protected final boolean compareAndSetState(int expect, int update)
return STATE.compareAndSet(this, expect, update);
static final long SPIN_FOR_TIMEOUT_THRESHOLD = 1000L;
以上是关于AbstractQueuedSynchronizer 详解的主要内容,如果未能解决你的问题,请参考以下文章