问题
(1) aq的定位?
(2) aq的重要组成部分?
(3) aq运用的设计模式?
(4) aq的总体流程?
简介
aq的全称是AbstractQueuedSynchronizer,它的定位是为Java中几乎所有的锁和同步器提供一个基础框架。
在之前的章节中,我们一起学习了ReentrantLock, ReentrantReadWriteLock,信号量,CountDownLatch的源码,今天我们一起来对aq做个总结。
状态变量状态/h3>
aq中定义了一个状态变量状态,它有以下两种使用方法:
(1)互斥锁
当aq只实现为互斥锁的时候,每次只要原子更新状态的值从0变为1成功了就获取了锁,可重入是通过不断把国家原子更新加1实现的。
(2)互斥锁+共享锁
当aq需要同时实现为互斥锁+共享锁的时候,低16位存储互斥锁的状态,高16位存储共享锁的状态,主要用于实现读写锁。
互斥锁是一种独占锁,每次只允许一个线程独占,且当一个线程独占时,其它线程将无法再获取互斥锁及共享锁,但是它自己可以获取共享锁。
共享锁同时允许多个线程占有,只要有一个线程占有了共享锁,所有线程(包括自己)都将无法再获取互斥锁,但是可以获取共享锁。
aq队列
aq中维护了一个队列,获取锁失败(非tryLock())的线程都将进入这个队列中排队,等待锁释放后唤醒下一个排队的线程(互斥锁模式下)。
条件队列
aq中还有另一个非常重要的内部类ConditionObject,它实现了条件接口,主要用于实现条件锁。
ConditionObject中也维护了一个队列,这个队列主要用于等待条件的成立,当条件成立时,其它线程将信号这个队列中的元素,将其移动到aq的队列中,等待占有锁的线程释放锁后被唤醒。
条件典型的运用场景是在BlockingQueue中的实现,当队列为空时,获取元素的线程阻塞在notEmpty条件上,一旦队列中添加了一个元素,将通知notEmpty条件,将其队列中的元素移动到aq队列中等待被唤醒。
模板方法
aq这个抽象类把模板方法设计模式运用地炉火纯青,它里面定义了一系列的模板方法,比如下面这些:
<代码类="语言java ">//获取互斥锁 公众最终无效收购(int参数){//tryAcquire (arg)需要子类实现 如果(! tryAcquire (arg),, acquireQueued (addWaiter (Node.EXCLUSIVE),参数) selfInterrupt (); }//获取互斥锁可中断 公共最后空白acquireInterruptibly (int参数) 抛出InterruptedException { 如果(Thread.interrupted ()) 抛出InterruptedException ();//tryAcquire (arg)需要子类实现 如果(! tryAcquire (arg)) doAcquireInterruptibly (arg); }//获取共享锁 公众最终无效acquireShared (int参数){//tryAcquireShared (arg)需要子类实现 如果(tryAcquireShared (arg) & lt;0) doAcquireShared (arg); }//获取共享锁可中断 公共最后空白acquireSharedInterruptibly (int参数) 抛出InterruptedException { 如果(Thread.interrupted ()) 抛出InterruptedException ();//tryAcquireShared (arg)需要子类实现 如果(tryAcquireShared (arg) & lt;0) doAcquireSharedInterruptibly (arg); }//释放互斥锁 公众最终布尔释放(int参数){//tryRelease (arg)需要子类实现 如果(tryRelease (arg)) { 节点h=头; 如果(h !=零,,h。waitStatus !=0) unparkSuccessor (h); 返回true; } 返回错误; }//释放共享锁 公众最终布尔releaseShared (int参数){//tryReleaseShared (arg)需要子类实现 如果(tryReleaseShared (arg)) { doReleaseShared (); 返回true; } 返回错误; }代码>
获取锁,释放锁的这些方法基本上都穿插在ReentrantLock, ReentrantReadWriteLock,信号量,CountDownLatch的源码解析中了,现在看他们是不是舒服多了,如果一开始就看这些源码,难免会很晕。
需要子类实现的方法
上面一起学习了aq中几个重要的模板方法、下面我们再一起学习下几个需要子类实现的方法:
<代码类="语言java ">//互斥模式下使用:尝试获取锁 保护布尔tryAcquire (int参数){ 抛出UnsupportedOperationException()方式; }//互斥模式下使用:尝试释放锁 保护布尔tryRelease (int参数){ 抛出UnsupportedOperationException()方式; }//共享模式下使用:尝试获取锁 保护int tryAcquireShared (int参数){ 抛出UnsupportedOperationException()方式; }//共享模式下使用:尝试释放锁 保护布尔tryReleaseShared (int参数){ 抛出UnsupportedOperationException()方式; }//如果当前线程独占着锁,返回现实 保护布尔isHeldExclusively () { 抛出UnsupportedOperationException()方式; }死磕java同步系列之aq终篇(面试)