万字超强图文讲解AQS以及ReentrantLock应用(建议收藏) (3)

自定义的同步组件或者锁不可能既是独占式又是共享式,为了避免强制重写不相干方法,所以就没有 abstract 来修饰了,但要抛出异常告知不能直接使用该方法:

protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException(); }

暖暖的很贴心(如果你有类似的需求也可以仿照这样的设计)

表格方法描述中所说的同步状态就是上文提到的有 volatile 修饰的 state,所以我们在重写上面几个方法时,还要通过同步器提供的下面三个方法(AQS 提供的)来获取或修改同步状态:

万字超强图文讲解AQS以及ReentrantLock应用(建议收藏)

而独占式和共享式操作 state 变量的区别也就很简单了

万字超强图文讲解AQS以及ReentrantLock应用(建议收藏)

所以你看到的 ReentrantLock ReentrantReadWriteLock Semaphore(信号量) CountDownLatch 这几个类其实仅仅是在实现以上几个方法上略有差别,其他的实现都是通过同步器的模版方法来实现的,到这里是不是心情放松了许多呢?我们来看一看模版方法:

同步器提供的模版方法

上面我们将同步器的实现方法分为独占式和共享式两类,模版方法其实除了提供以上两类模版方法之外,只是多了响应中断和超时限制 的模版方法供 Lock 使用,来看一下

万字超强图文讲解AQS以及ReentrantLock应用(建议收藏)

先不用记上述方法的功能,目前你只需要了解个大概功能就好。另外,相信你也注意到了:

上面的方法都有 final 关键字修饰,说明子类不能重写这个方法

看到这你也许有点乱了,我们稍微归纳一下:

万字超强图文讲解AQS以及ReentrantLock应用(建议收藏)

程序员还是看代码心里踏实一点,我们再来用代码说明一下上面的关系(注意代码中的注释,以下的代码并不是很严谨,只是为了简单说明上图的代码实现):

package top.dayarch.myjuc; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.AbstractQueuedSynchronizer; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; /** * 自定义互斥锁 * * @author tanrgyb * @date 2020/5/23 9:33 PM */ public class MyMutex implements Lock { // 静态内部类-自定义同步器 private static class MySync extends AbstractQueuedSynchronizer{ @Override protected boolean tryAcquire(int arg) { // 调用AQS提供的方法,通过CAS保证原子性 if (compareAndSetState(0, arg)){ // 我们实现的是互斥锁,所以标记获取到同步状态(更新state成功)的线程, // 主要为了判断是否可重入(一会儿会说明) setExclusiveOwnerThread(Thread.currentThread()); //获取同步状态成功,返回 true return true; } // 获取同步状态失败,返回 false return false; } @Override protected boolean tryRelease(int arg) { // 未拥有锁却让释放,会抛出IMSE if (getState() == 0){ throw new IllegalMonitorStateException(); } // 可以释放,清空排它线程标记 setExclusiveOwnerThread(null); // 设置同步状态为0,表示释放锁 setState(0); return true; } // 是否独占式持有 @Override protected boolean isHeldExclusively() { return getState() == 1; } // 后续会用到,主要用于等待/通知机制,每个condition都有一个与之对应的条件等待队列,在锁模型中说明过 Condition newCondition() { return new ConditionObject(); } } // 聚合自定义同步器 private final MySync sync = new MySync(); @Override public void lock() { // 阻塞式的获取锁,调用同步器模版方法独占式,获取同步状态 sync.acquire(1); } @Override public void lockInterruptibly() throws InterruptedException { // 调用同步器模版方法可中断式获取同步状态 sync.acquireInterruptibly(1); } @Override 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 public void unlock() { // 释放锁 sync.release(1); } @Override public Condition newCondition() { // 使用自定义的条件 return sync.newCondition(); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyfypd.html