一图解释ReentranLock底层原理
2021-09-28 17:23:56   32  举报             
     
         
 一图解释ReentranLock底层原理
    作者其他创作
 大纲/内容
 1.先尝试获取锁
  否
  继承
    超类
  acquire(1)
  添加成功
  state == 0没有被线程占用
  Sync锁是否被线程占用?state = 0?
  将当前队列添加到CLH队列尾
  Lock
  调用
  注意:CLH队列会维护一个前驱节点,当前节点的pred == null 才是头节点,目的是方便判断,进行状态转换时也会简单许多
  false
  修改Sync对象State的值nextc = c + acquiressetState(nextc)
  总结:如果锁没有被占用,非公平锁直接尝试获取锁,公平锁先判断是否有等待线程,没有再尝试获取锁。如果被线程占用则判断是否是当前线程占用,是就修改state状态,没有直接返回false执行后续代码
  !非公平锁不判断直接尝试获取锁
  ReentrantLock
  当前节点是否为队列中的第一个节点?node.predecessor() == head ?
  失败
  是
  Nonfair
  true
  free = true
  模板方法模式
  头节点不为空,且waitStaaatus不为0
  FairSync
  设置当前线程独占锁setExclusiveOwnerThread(Thread.currentThread())
  设置当前占用访问权线程为nullsetExclusiveOwnerThread(null)
  设置新的statesetState(c)
  计算新的statec = getState() - releases如果不是当前线程占用锁抛异常
  尝试获取锁成功返回TRUE
  设置当前拥有独占访问权的线程
  总结:入CLH队列后尝试获取锁,先判断是否为第一个节点,是的话尝试获取锁,未获取到锁或不是第一个节点且非阻塞会进行自旋,重复尝试获取锁,如果阻塞,返回当前中断状态
  新的statec == 0 ?
  3.在CLH队队列中尝试获取锁
  初始化CLH队列compareAndSetHead(new Node())tail = head
  Sync
  getState()
  release(1)
  !tryAcquire(arg)
  未获取到锁
  添加失败自旋保证队列全部入队
  尝试获取锁失败返回FALSE继续执行后续代码
  同步队列中是否有等待线程 Node pred = tailpred != null ?
  获取到锁
  unLock()
  tryRelease(arg) ?
  实现
  返回当前线程是否中断
  是否是当前线程占用?current == getExclusiveOwnerThread()
  LockSupport.unpark(s.thread)解除s.thread线程的阻塞
  AbstractQueuedSynchronizer
  selfInterrupt()->Thread.currentThread().interrupt()设置打断标记,将中断信号外传
  逻辑
  是这个类中的方法
  return free
  2.添加当前线程到CLH队列中EXCLSIVE独占模式
  state != 0被线程占用
  自我中断设置打断标记
  setExclusiveOwnerThread()
  将当前线程对应的Node对象从CLH队列移除,并重新设置队列
  free = false
  lock()
  当前线程不再占用锁
  成功
  方法
  判断CLH队列中是否等待的线程!hasQueuedPredecessors()
  尝试获取锁tryAcquire()
  Node h = headh != null && waitStatus != 0 
  总结:线程加锁失败后,将当前线程添加到CLH队列,如果队列中有等待线程,将当前队列添加到队列尾部,如果没有,先检查是否初始化,初始化了就添加到队列尾部,未初始化就先初始化一个队列再添加
  AbstractOwnableSynchronizer
  队列是否初始化tail == null ?
  返回当前线程对应的Node对象
  addWaiter(Node.EXCLUSIVE)
  返回false
  Fair无论成功失败
  getExclusiveOwnerThread()
  是队列中有等待线程
  类/接口
  否自旋重复执行for循环尝试获取锁
  unparkSuccessor(h)唤醒节点的后继节点(如果存在)
  阻塞当前线程,返回当前线程中断状态parkAndCheckInterrupt()
  内部类
  获取当前拥有独占访问权的线程
  添加当前线程到队列中enq(Node)
  NonfairSync
   
 
 
 
 
  0 条评论
 下一页
  
   
   
   
   
  
  
  
  
  
  
  
  
 