AQS
全称是 AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架
特点:
- 用 state 属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取锁和释放锁
- getState - 获取 state 状态
- setState - 设置 state 状态
- compareAndSetState - cas 机制设置 state 状态
- 独占模式是只有一个线程能够访问资源,而共享模式可以允许多个线程访问资源 提供了基于 FIFO 的等待队列,类似于 Monitor 的 EntryList 条件变量来实现等待、唤醒机制,支持多个条件变量,类似于 Monitor 的 WaitSet(AQS 是 Java 实现,sychronized 是 c++ 实现)
用 AQS 自定义不可重入锁
tryAcquire 在 AQS 原代码里是可重入锁,这里继承了 AQS,将其重写为不可重入锁了
不可重入锁:本线程加了锁,那么后续本线程还想继续加锁,加锁是不成功的
final class MySync extends AbstractQueuedSynchronizer { @Override protected boolean tryAcquire(int acquires) { // int acquires 是可重入锁用来计数的。现在不可重入锁暂时用不到 if (acquires == 1){ // 通过设置 aqs 的 state 获得锁,初始值0,改为1代表获得了锁 // 为了防止其它线程一起来修改 state 状态,所以用 compareAndSet if (compareAndSetState(0, 1)) { // 加锁成功后,设置 owner 线程为当前线程 setExclusiveOwnerThread(Thread.currentThread()); return true; } } // CAS 失败,即加锁失败 return false; }
@Override protected boolean tryRelease(int acquires) { if(acquires == 1) { // state=0表示当前没加锁,却要释放,抛出异常 if(getState() == 0) { throw new IllegalMonitorStateException(); } // 置空当前线程。ExclusiveOwnerThread 在 AQS 里不是 volatile 的 setExclusiveOwnerThread(null); // state 在 AQS 里是 volatile 的,所以要放在后面,加写屏障,防止之前的指令重排 setState(0); return true; } return false; }
protected Condition newCondition() { // aqs 提供的类 return new ConditionObject(); }
@Override protected boolean isHeldExclusively() { // 是否持有独占锁 return getState() == 1; } }
原代码里的 acquire ,用 tryAcquire 尝试获取锁不成功,就放入等待队列中(添加到一个链表中,并 LockSupport.park(this))
我们重写了 tryAcquire 方法为不可重入锁,所以这里的尝试获取锁会调用我们重写的方法,即获取不可重入锁
public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
原代码里的 release,用 tryRelease 尝试释放锁成功后,还会唤醒等待队列上的线程(从链表中移除,并用 LockSupport.unpark(node.thread) 唤醒)
我们重写了 tryRelease 方法为不可重入锁释放,所以这里的尝试释放锁会调用我们重写的方法,即释放不可重入锁
public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; }
对 MySync 的封装
class MyLock implements Lock { static MySync sync = new MySync(); @Override // 尝试获取锁(被重写的tryAcquire),不成功,进入等待队列(AQS的逻辑) public void lock() { sync.acquire(1); } @Override // 尝试,不成功,进入等待队列,可打断 public void lockInterruptibly() throws InterruptedException { sync.acquireInterruptibly(1); } @Override // 尝试一次,不成功返回,不进入队列(acquire 是 tryAcquire 进行的封装,失败会进入等待队列) 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 // 释放锁。tryRelease 只会释放锁,release 还会唤醒等待的线程 public void unlock() { sync.release(1); } @Override // 生成条件变量 public Condition newCondition() { return sync.newCondition(); } }
测试
MyLock lock = new MyLock(); new Thread(() -> { lock.lock(); try { log.debug("locking..."); sleep(1); } finally { log.debug("unlocking..."); lock.unlock(); }
},"t1").start();
new Thread(() -> { lock.lock(); try { log.debug("locking..."); } finally { log.debug("unlocking..."); lock.unlock(); } },"t2").start();