独占模式请求锁acquire()
- 尝试获取锁tryAcquire
- true => 继续运行
- false=>执行addWaiter,获取返回的node作为acquireQueued的参数执行
- acquireQueued(addWaiter())==true=>
- acquireQueued(addWaiter())==false=>
-
addWaiter
- 封装当前结点,判断tail是否为空
- true=>直接执行enq用自旋方式初始化队头head,并在下一次循环cas(tail,node)将tail设置为node,此时node在队尾
- false=>将tail的next设置为node,并执行enq(),cas(tail,node),此时node在队尾。
- 返回node
- 封装当前结点,判断tail是否为空
-
acquireQueued
- failed = true; interrupted = false;
- 进入自旋循环
- 判断前驱是否为head
- true=>尝试获得锁tryAcquire
- true=>设置当前node为head,设置failed=false,返回interrupted的值
- false=>检查node是否需要阻塞shouldParkAfterFailedAcquire
- true=>执行parkAndCheckInterrupt()阻塞线程,并返回阻塞结果
- 阻塞结果后,设置interrupted = true
- true=>尝试获得锁tryAcquire
-
shouldParkAfterFailedAcquire
- 前驱结点状态为SIGNAL时,返回true,代表需要阻塞
- 前驱结点状态为CANCELLED时 ,说明要删除已被撤销的前驱结点,循环把CANCELLED状态的前驱结点全部删除。返回false。
- 前驱接点为0,CONDITION,PROPAGATE状态下时,需要被设置为SIGNAL,等待被唤醒。返回false。
独占模式释放锁release()
- 尝试获取锁tryAcquire
- true=>判断线程队列头的状态,不为零则进入unparkSuccessor方法中断线程阻塞
- false=>锁释放失败
- 返回true,锁释放成功
-
unparkSuccessor
- 头结点的waitStatus小于0(SIGNAL或CONDITION)时,用cas设置为0
- 寻找头结点的下一个结点Node s = head.next
- 该结点为空,则使用尾结点前驱查找需唤醒节点,然后赋给s
- 再次判断该结点s是否为空,不为空则中断阻塞。
- 在中断阻塞之后,其实就是继续运行acquireQueued中的parkAndCheckInterrupt的Thread.interrupted方法得到true,并将interrupted赋为true并且进入acquireQueued自旋的下一个循环时,会将头结点后移。抛弃原本的head。
网友评论