什么是AQS
AbstractQueuedSynchronizer(抽象队列同步器,简称AQS)出现在JDK 1.5中。AQS是很多同步器的基础框架,比如ReentrantLock、CountDownLatch和Semaphore等都是基于AQS实现的。除此之外,我们还可以基于AQS,定制出我们所需要的同步器。注意AQS是同步器是辅助我们更快捷的实现各种锁的框架, 并不是锁!!!
基于AQS实现自己的锁
由于AQS类中, 很多方法都是final的方法, 其实我们只需要重写部分方法就可以了. 可重写方法如下图, 而且这些方法AQS是要求使用者必须自己实现的, 否则会抛出UnsupportedOperationException
异常.
自定义实现同步器:
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;/*** 同步器类*/
public class MySynchronizer extends AbstractQueuedSynchronizer {@Overrideprotected boolean tryAcquire(int arg) {// cas修改锁状态, compareAndSetState方法是AQS中的方法if (super.compareAndSetState(0, 1)) {// cas修改状态成功, 即加锁成功. 设置owner线程super.setExclusiveOwnerThread(Thread.currentThread());}return false;}@Overrideprotected boolean tryRelease(int arg) {setExclusiveOwnerThread(null);// state是volatile修饰的, 有写屏障, 所以放在setExclusiveOwnerThread方法后执行. 可以保证exclusiveOwnerThread的可见性setState(0);return true;}/*** 是否持有独占锁* @return*/@Overrideprotected boolean isHeldExclusively() {return getState() > 0;}public Condition newCondition() {return new ConditionObject();}
}
自定义实现锁
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;/*** 自定义不可重入锁*/
public class MyLock implements Lock {private MySynchronizer sync = new MySynchronizer();/*** 加锁, 加锁失败, 进入队列等待*/@Overridepublic void lock() {sync.acquire(1);}/*** 可打断的加锁* @throws InterruptedException*/@Overridepublic void lockInterruptibly() throws InterruptedException {sync.acquireInterruptibly(1);}/*** 尝试加锁, 加锁失败返回;不会等待* @return*/@Overridepublic boolean tryLock() {return sync.tryAcquire(1);}/*** 尝试加锁, 有等待时间* @param time the maximum time to wait for the lock* @param unit the time unit of the {@code time} argument* @return* @throws InterruptedException*/@Overridepublic boolean tryLock(long time, TimeUnit unit) throws InterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(time));}/*** 解锁*/@Overridepublic void unlock() {sync.release(1);}/*** 创建条件变量* @return*/@Overridepublic Condition newCondition() {return sync.newCondition();}
}