你的位置:首页 > 软件开发 > Java > 再谈AbstractQueuedSynchronizer:独占模式

再谈AbstractQueuedSynchronizer:独占模式

发布时间:2017-06-23 12:00:55
关于AbstractQueuedSynchronizerJDK1.5之后引入了并发包java.util.concurrent,大大提高了Java程序的并发性能。关于java.util.concurrent包我总结如下:AbstractQueuedSynchronizer是并发类诸 ...

再谈AbstractQueuedSynchronizer:独占模式

关于AbstractQueuedSynchronizer

JDK1.5之后引入了并发包java.util.concurrent,大大提高了Java程序的并发性能。关于java.util.concurrent包我总结如下:

  • AbstractQueuedSynchronizer是并发类诸如ReentrantLock、CountDownLatch、Semphore的核心
  • CAS算法是AbstractQueuedSynchronizer的核心

可以说AbstractQueuedSynchronizer是并发类的重中之重。其实之前在ReentrantLock实现原理深入探究一文中已经有结合ReentrantLock详细解读过AbstractQueuedSynchronizer,但限于当时水平原因,回看一年半前的此文,感觉对于AbstractQueuedSynchronizer的解读理解还不够深,因此这里更新一篇文章,再次解读AbstractQueuedSynchronizer的数据结构即相关源码实现,本文基于JDK1.7版本。

 

AbstactQueuedSynchronizer的基本数据结构

AbstractQueuedSynchronizer的基本数据结构为Node,关于Node,JDK作者写了详细的注释,这里我大致总结几点:

  1. AbstractQueuedSynchronizer的等待队列是CLH队列的变种,CLH队列通常用于自旋锁,AbstractQueuedSynchronizer的等待队列用于阻塞同步器
  2. 每个节点中持有一个名为"status"的字段用于是否一条线程应当阻塞的追踪,但是status字段并不保证加锁
  3. 一条线程如果它处于队列的头,那么他会尝试去acquire,但是成为头并不保证成功,它只是有权利去竞争
  4. 要进入队列,你只需要自动将它拼接在队列尾部即可;要从队列中移除,你只需要设置header字段

下面我用一张表格总结一下Node中持有哪些变量且每个变量的含义:

再谈AbstractQueuedSynchronizer:独占模式

关于SIGNAL、CANCELLED、CONDITION、PROPAGATE四个状态,JDK源码的注释中同样有了详细的解读,再用一张表格总结一下:

再谈AbstractQueuedSynchronizer:独占模式

 

AbstractQueuedSynchronizer供子类实现的方法

AbstractQueuedSynchzonizer是基于模板模式的实现,不过它的模板模式写法有点特别,整个类中没有任何一个abstract的抽象方法,取而代之的是,需要子类去实现的那些方法通过一个方法体抛出UnsupportedOperationException异常来让子类知道。

AbstractQueuedSynchronizer类中一共有五处方法供子类实现,用表格总结一下:

再谈AbstractQueuedSynchronizer:独占模式

这里的acquire不好翻译,所以就直接原词放上来了,因为acquire是一个动词,后面并没有带宾语,因此不知道具体acquire的是什么。按照我个人理解,acquire的意思应当是根据状态字段state去获取一个执行当前动作的资格

比如ReentrantLock的lock()方法最终会调用acquire方法,那么:

  1. 线程1去lock(),执行acquire,发现state=0,因此有资格执行lock()的动作,将state设置为1,返回true
  2. 线程2去lock(),执行acquire,发现state=1,因此没有资格执行lock()的动作,返回false

这种理解我认为应当是比较准确的。

 

独占模式acquire实现流程

有了上面的这些基础,我们看一下独占式acquire的实现流程,主要是在线程acquire失败后,是如何构建数据结构的,先看理论,之后再用一个例子画图说明。

看一下AbstractQuueuedSynchronizer的acquire方法实现流程,acquire方法是用于独占模式下进行操作的:

 1 public final void acquire(int arg) { 2   if (!tryAcquire(arg) && 3     acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) 4     selfInterrupt(); 5 }

 

海外公司注册、海外银行开户、跨境平台代入驻、VAT、EPR等知识和在线办理:https://www.xlkjsw.com

原标题:再谈AbstractQueuedSynchronizer:独占模式

关键词:

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

可能感兴趣文章

我的浏览记录