文章目录
- 1. 简介
- 2. 基于AQS实现自定义锁
1. 简介
AQS时AbstractQueueSynchronizer,是阻塞式锁的同步器工具的框架。AQS 是一个用来构建锁和同步器的框架,使用 AQS 能简单且高效地构造出应用广泛的大量的同步器。特点如下:
- 用State属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取锁和释放锁
- getState:获取state状态
- setState:设置state状态
- compareAndSetState:CAS机制设置State状态
- 独占模式是只有一个线程能够访问资源,而共享模式可以运行多个线程访问资源
- 提供了基于FIFO的等待队列,类似于Monitor的EntryList
- 条件变量来实现等待和唤醒机制,支持多个条件变量,类似于Monitor的WaitSet
子类主要实现这样一些方法(默认抛出UnsupportedOperationException)
- tryAcquire
- tryRelease
- tryAcquireShared
- tryReleaseShared
- isHeldExclusively
获取锁
//如果获取锁失败
if(!tryAcquire(arg)){//入锁,可以选择阻塞当前线程,park和unpark机制实现
}
释放锁
//如果释放锁成功
if(tryRelease(arg)){}
2. 基于AQS实现自定义锁
//自定义锁类(这里是不可重用锁)
class Mylock implements Lock {//实现同步器类(我这里实现独占锁)class Mysync extends AbstractQueuedSynchronizer {@Overrideprotected boolean tryAcquire(int arg) {if (compareAndSetState(0, 1)) {//加锁成功,设置当前锁的ownersetExclusiveOwnerThread(Thread.currentThread());return true;}return false;}@Overrideprotected boolean tryRelease(int arg) {setState(0);setExclusiveOwnerThread(null);return true;}@Override //是否持有独占锁protected boolean isHeldExclusively() {return getState() == 1;}public Condition newCondition() {return new ConditionObject();}}private Mysync mysync = new Mysync();//用于加锁(不成功则进入等待队列等待)@Overridepublic void lock() {mysync.acquire(1);}//可打断的加锁@Overridepublic void lockInterruptibly() throws InterruptedException {mysync.acquireInterruptibly(1);}//尝试加锁@Overridepublic boolean tryLock() {return mysync.tryAcquire(1);}//尝试加锁,带超时时间@Overridepublic boolean tryLock(long time, TimeUnit unit) throws InterruptedException {return mysync.tryAcquireNanos(1,unit.toNanos(time));}@Overridepublic void unlock() {mysync.release(1);}//创建条件变量@Overridepublic Condition newCondition() {return mysync.newCondition();}
}
测试自己实现的自定义锁
@Slf4j
public class TestFinal {public static void main(String[] args) {Mylock mylock=new Mylock();new Thread(()->{mylock.lock();try{log.debug("locking.....");Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);} finally {log.debug("unlocking....");mylock.unlock();}},"t1").start();new Thread(()->{mylock.lock();try{log.debug("locking.....");}finally {log.debug("unlocking....");mylock.unlock();}},"t2").start();}
}