zoukankan      html  css  js  c++  java
  • java源码ReentrantLock源码分析1

    ReentrantLock 继承于lock是比较常用的独占锁,接下来我们来分析一下ReentrantLock源码以及接口设计

    Sync是ReentrantLock的内部静态抽象类继承AbstractQueuedSynchronizer类,ReentrantLock类部还有两个类FairSync(公平锁)跟NonfairSync(非公平锁)类实现Sync;

     ReentrantLock默认内部是构建非公平锁,也可以制定使用公平锁跟非公平锁,

    当调用lock()方法时,下面分析公平锁跟非公平区别:

    lock()具体指向内部实例化的Sync对象

    公平锁lock()方法直接调用acquire(1)直接尝试获取一次锁(第一次由于锁被抢占,加入队列时判断是否锁已经释放),如果失败后则加入队列

    非公平锁,首先通过cas强行获取一次锁,失败后在调用acquire(1)尝试获取锁失败后加入队列

    tryAcquire(1)方法实现也不同  非公平锁最终会调用Sync对象的nofairTryAcquire()方法,当state=0代表没有锁占用,此时会调用cas强行占用锁,

    这时候如果同时新加入的线程抢占锁失败,导致后加入的锁进入队列,这时候体现无序不公平。

    公平锁首先hasQueuedPredecessors()判断没有前驱节点代表是head节点然后再获取锁,

    不管是公平锁还是非公平锁都支持重入锁,直接把state计数+1;

    acquireQueued()方法主要左右是将实例化当前线程绑定Node节点加入队列并修改前驱节点Node的waitStatus为SIGNAL,同时并挂起当前节点;

    首先new Node节点绑定线程,独占锁默认nextWaiter为空,如果存在tail节点然后通过cas添加tail节点,如果不存在会调用enq(node)方法初始化head节点

    此时再次判断tail节点是否为空,如果为空然后cas添加一个空节点然后进入空转,下次循环再cas添加节点都tail节点,这里有人会疑问为什么会添加一个空Node节点而且并没有

    绑定线程?

    首先获取前驱节点,如果前驱节点是头节点,然后尝试获取一下锁,如果成功则设置当前node为head节点然后将前驱节点移除队列;

    如果前驱节点不是头节点或者获取锁失败,此时进入shouldParkAfterFailedAcquire()方法

     如果前驱节点是SIGNAL=-1则表示是可以挂起线程,等待前驱节点唤醒,如果前驱节点是刚才new Node() 的话

    ws=0此时将会cas修改状态为SIGNAL,然后返回false然后进入自旋,再次进入此方法则再挂起当前线程。最后形成的链表处tail节点都是signal状态切线程状态都是挂起,

    等待释放然后唤起header节点的next节点。

     

  • 相关阅读:
    HTML 语义化标签-新增标签介绍
    HTML基础知识点
    Android JSON 解析关键代码
    [USACO16DEC]Cities and States省市
    [洛谷P1835]素数密度
    [洛谷P1168]中位数
    [HNOI2008]越狱
    [HAOI2007]上升序列
    [SHOI2009]Booking 会场预约
    [洛谷P1892][codevs2597]团伙
  • 原文地址:https://www.cnblogs.com/1ssqq1lxr/p/9490572.html
Copyright © 2011-2022 走看看