并发编程之AQS框架
目录
一、定义
AQS是AbstactQueuedSynchronizer的简称,它是一个Java提供的底层同步工具类,用一个int类型的变量表示同步状态,并提供了一系列的CAS操作来管理这个同步状态。AQS的主要作用是为Java中的并发同步组件提供统一的底层支持,例如ReentrantLock,CountdowLatch就是基于AQS实现的,用法是通过继承AQS实现其模版方法,然后将子类作为同步组件的内部类。
总结:
- 全称是AbstactQueuedSynchronizer
- 阻塞式锁和相关的同步工具的框架
- AQS用一个变量(volatile state)属性表示锁的状态,子类去维护这个状态
- 使用getState、compareAndSetState、cas改变这个变量
- 独占锁模式是只有一个线程能够访问资源
- 共享锁模式可以允许多个线程访问资源(读写锁)
- 内部维护了一个FIFO等待队列,类似于synchronized关键子中的Monitor中的EntryList
- 支持多个条件变量,实现等待唤醒机制,类似synchronized中的WaitSet
- 内部维护了一个Thread exclusiveOwerThread来记录当前持有锁的那个线程
二、自定义实现AQS框架
既然AQS是一个框架,那我们就基于它实现一个自定义锁工具。
继承AbstractQueuedSynchronizer,并重写其中的方法。
public class CustomSync extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire(int arg) {
if (compareAndSetState(0, arg)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
@Override
protected boolean tryRelease(int arg) {
if(getState() == 0) {
throw new IllegalMonitorStateException();
}
setExclusiveOwnerThread(null);
setState(0);
return true;
}
/**
* 判断这把锁当前有没有被人持有
* @return
*/
@Override
protected boolean isHeldExclusively() {
return getState()==1;
}
public Condition newCondition() {
return new ConditionObject();
}
}
测试类:
@Slf4j(topic = "liheng")
public class TestLock implements Lock {
CustomSync customSync = new CustomSync();
/**
* 加锁
*/
@Override
public void lock() {
customSync.acquire(1);
}
@Override
public void lockInterruptibly() throws InterruptedException {
customSync.acquireInterruptibly(1);
}
@Override
public boolean tryLock() {
return customSync.tryAcquire(1);
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return customSync.tryAcquireNanos(1, unit.toNanos(time));
}
@Override
public void unlock() {
customSync.release(1);
}
@Override
public Condition newCondition() {
return customSync.newCondition();
}
public static void main(String[] args) throws InterruptedException {
TestLock l = new TestLock();
new Thread(()->{
l.lock();
log.debug("xxx");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
l.unlock();
},"t1").start();
TimeUnit.SECONDS.sleep(1);
l.lock();
log.debug("main");
l.unlock();
}
}
/**
-----------------结果打印-------------------
19:36:56.644 [t1] DEBUG liheng - xxx
19:37:01.647 [main] DEBUG liheng - main
*/
执行代码发现自己写的工具锁生效。