ReentrantLock 公平锁加锁流程图
2023-03-21 20:24:59   0  举报             
     
         
 ReentrantLock 公平锁加锁流程图
    作者其他创作
 大纲/内容
 thread=t3
  是
  CAS head为new Node()
    waitStatus=0
  将tNode设为head,将tNode的thread和prev设为nullhead原先指向的node会被GC
  HEAD
  成功
  prev
  thread=t1
  thread=thread4prev=nullnext=null
  waitStatus=-1
  next
  CAS将tNode设为tail
  否
  waitStatus=1
  CAS为state+1成败
  thread=null
  thread=tNode
  编号5
  true/false
  thread=t2
  Node t=tail判断t是否为空
  是第一个,要再自旋一次尝试获取锁tryAcquire()
  判断p的waitStatus是否==0
  无排队状态
  创建当前线程的Node:tNode
  给p节点的waitStatus赋值为-1
  当前队列一定为空(对应下方编号2)
  enq(tNode)
  编号0
  继续循环
  TAIL
  编号2
  p = p.prev;node.prev =p;跳过所有cancel状态的节点
  HEAD&TAIL
  tNode
  判断是否需要排队hasQueuedPredecessors()
  将head赋值给tailtail=head
  有另一个专门兼容线程Interupt的加锁方法——lockInterruptibly,关于shouldParkAfterFailedAcquire、parkAndCheckInterrupt 方法和acquireQueued方法中,Thread.Interupt()的逻辑,在lock方法里可以完全忽略。该逻辑仅在使用lockInterruptibly加锁时有用。
  等待队列结构概览
  判断lock的state是否为0
  tail
  prev=null
  如下方编号0中的t3,waitStatus为1
  此时tNode一定是tail了
  判断p的waitStatus是否为-1
  Node pred=tail判断pred是否为空
  加锁成功设置exclusiveOwnerThread为当前线程
  将前一个节点指向tNodepred=tNode.prev
  false
  编号1
  t.next=tNode
  编号4
  第一个排队线程添加完成后
  Node p=tNode.prev判断p是否为head
  加锁失败
  编号3
  拿到锁之后,释放node
  tNode.prev=tail
  null
  tNode.prev=tt.next=tNode
  acquireQueued(tNode)
  第一次新增排队线程
  失败
  放置队列末尾(对应下方编号2345)
  判断当前锁的exclusiveOwnerThread是否为当前线程
  是即此线程是第一个排队的
  shouldParkAfterFailedAcquire(p,tNode)
  当前队列一定为空(对应下方编号1)
  tryAcquire()thread4
  LockSupport.park(this)当前线程开始阻塞
  true
  addWaiter()
  此时线程尚未park
  被unpark
   
 
 
 
 
  0 条评论
 下一页
  
   
   
  
  
  
  
  
  
  
  
 