欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识

再谈 AbstractQueued 劳务派遣信息管理系统 Synchronizer 1 :独有模式

点击: 次  来源:宝鼎软件 时间:2017-08-15

原文出处: 五月的仓颉

关于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中持有哪些变量且每个变量的寄义:

    再谈 AbstractQueued 劳务调派信息打点系统 Synchronizer 1 :独占模式

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

    再谈 AbstractQueued 劳务调派信息打点系统 Synchronizer 1 :独占模式 

    AbstractQueuedSynchronizer供子类实现的要领

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

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

    再谈 AbstractQueued 劳务调派信息打点系统 Synchronizer 1 :独占模式

    这里的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要领是用于独有模式下举办操纵的:

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

    tryAcquire要领前面说过了,是子类实现的一个要领,假如tryAcquire返回的是true(乐成),即表白当前线程得到了一个执行当前行动的资格,自然也就不需要构建数据布局举办阻塞期待。

    假如tryAcquire要领返回的是false,那么当前线程没有得到执行当前行动的资格,接着执行”acquireQueued(addWaiter(Node.EXCLUSIVE), arg))”这句代码,这句话很明明,它是由两步组成的:

    1. addWaiter,添加一个期待者
    2. acquireQueued,实验从期待行列中去获取执行一次acquire行动

    别离看一下每一步做了什么。

    addWaiter

    先看第一步,addWaiter做了什么,从传入的参数Node.EXCLUSIVE我们知道这是独有模式的:

    private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        Node prev = tail;
        if (prev != null) {
            node.prev = prev;
            if (compareAndSetTail(prev, node)) {
                prev.next = node;
                return node;
            }
        }
        enq(node);
        return node;
    }