AQS
全称:AbstractQueuedSynchronizer,译为:抽象队列同步器。
AQS是很多并发工具类的基础,可以说是实现整个java.util.concurrent并发包的半壁江山。
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable
AbstractQueuedSynchronizer是一个抽象类,本身不能实例化。
它用到了“模板方法设计模式”,定义了一个模板骨架,子类需要实现部分流程方法才能使用。
重要方法
-
int getState()
获取同步状态。 -
void setState()
设置同步状态。 -
boolean compareAndSetState(int expect, int update)
基于CAS操作来设置同步状态。
setState和compareAndSetState
这两个方法的区别是:一个是非原子的,一个是原子的。
什么时候用setState?
释放锁时使用setState,因为只有获取锁的线程才能调用该方法,不存在并发问题,所以无需使用CAS操作。
什么时候用compareAndSetState?
加锁时使用compareAndSetState,因为锁竞争时是并发的,设置同步状态操作必须是CAS的,否则可能多个线程同时加锁成功。
子类重写方法
AQS的功能可以分为两类:独占式与共享式。
独占式:同一时刻最多只允许一个线程获得锁,
共享式:同一时刻允许多个线程获得锁,
独占式
-
boolean tryAcquire(int arg)
独占式尝试获取锁。 -
boolean tryRelease(int arg)
独占式尝试释放锁。 -
boolean isHeldExclusively()
判断当前线程是否获取独占锁。
共享式
-
boolean tryAcquireShared(int arg)
共享式尝试获取锁。 -
boolean tryReleaseShared(int arg)
共享式尝试释放锁。
根据自己要实现的锁类型,重写对应的方法即可。
模板方法
AQS定义了一组模板方法,子类不允许重写,可直接调用。
独占式
-
void acquire(int arg)
独占式获取锁。 -
void acquireInterruptibly(int arg)
独占式获取锁,支持中断。 -
boolean tryAcquireNanos(int arg,long nanos)
独占式尝试获取锁,支持超时。 -
boolean release(int arg)
独占式释放锁。
共享式
-
void acquireShared(int arg)
共享式获取锁。 -
void acquireSharedInterruptibly(int arg)
共享式获取锁,支持中断。 -
boolean tryAcquireSharedNanos(int arg,long nanos)
共享式尝试获取锁,支持超时。 -
boolean releaseShared(int arg)
共享式释放锁。
自定义锁实例
MyLock
/**
* @Author: 潘
* @Date: 2019/11/23 16:18
* @Description: 基于Lock和AQS实现自定义锁
*/
public class MyLock implements Lock {
//AQS实例
private final Sync sync = new Sync();
/**
* 继承AQS 实现独占锁
* state 0无锁 1有锁
*/
static class Sync extends AbstractQueuedSynchronizer{
/**
* 重写tryAcquire
* 获取锁成功和失败均输出提示文字
* @param arg
* @return
*/
@Override
protected boolean tryAcquire(int arg) {
if (compareAndSetState(0, arg)) {
//设置独占锁线程为当前线程
setExclusiveOwnerThread(Thread.currentThread());
System.out.println(Thread.currentThread().getName()+"锁竞争成功");
return true;
}
System.out.println(Thread.currentThread().getName()+"锁竞争失败");
return false;
}
//尝试释放锁
@Override
protected boolean tryRelease(int arg) {
setState(arg);
setExclusiveOwnerThread(null);
return true;
}
@Override
protected boolean isHeldExclusively() {
return super.isHeldExclusively();
}
}
@Override
public void lock() {
sync.acquire(1);
}
@Override
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
@Override
public boolean tryLock() {
return sync.tryAcquire(1);
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(time));
}
@Override
public void unlock() {
sync.release(0);
}
@Override
public Condition newCondition() {
return sync.new ConditionObject();
}
}
测试
class MyLockDemo{
private MyLock lock = new MyLock();
void test(){
lock.lock();
SleepUtil.sleep(1000);
System.out.println(Thread.currentThread().getName());
lock.unlock();
}
public static void main(String[] args) {
MyLockDemo demo = new MyLockDemo();
for (int i = 0; i < 3; i++) {
new Thread(()->{
demo.test();
}).start();
}
}
}
输出如下:
Thread-0锁竞争成功
Thread-2锁竞争失败
Thread-1锁竞争失败
Thread-2锁竞争失败
Thread-2锁竞争失败
Thread-0
Thread-2锁竞争成功
Thread-2
Thread-1锁竞争成功
Thread-1