AQS 源码解读

1.先看一下类图

2.开始跟代码

找一个入口

new ReentrantLock()默认是非公平锁,false是非公平

进入lock.lock(),在 ReentrantLock中的实现

看到是sync的lock方法 Sync 是ReentrantLock的子类 

找抽象方法lock()在非公平锁中的实现

compareAndSetState(0,1) 如果状态是0 更新为 1
setExclusiveOwnerThread(Thread.currentThread()); 设置持有线程为当前线程

如果当前状态不是0,则 运行 acquire(1)

看!tryAcquire(arg)方法,进入是一个 

找他在非公平锁中的实现

显然状态不是0,当前线程也不是线程执行占有者 返回false;

返回到这张图:!tryAcquire(arg) == true

再看另一个条件 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)

进入代码前先看一下Node的几个状态

再看addWaiter(Node.EXCLUSIVE) 添加等待者,为当前线程创建一个队列节点

现在AQS的tail == null,所以直接进入enq(node);

一个自旋, 

第一次循环t==null, AQS的head和tail 都设置成 new Node();

第二次循环 t != null 这个新结点 前指针指向当前线程,tail也指向当前线程

 

返回到 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)

final Node p = node.predecessor();获取node的prev节点,而第一个节点是一个空节点 哨兵节点
p == head is true   
如果再次尝试获取(tryAcquire(arg))失败返回false lock()方法结束
但是再次尝试获取失败 进入 
if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())

pred.waitStatus 节点默认为0, 运行 compareAndSetWaitStatus(pred, ws, Node.SIGNAL)

把pred.waitStatus 设置成 -1 ,再次循环进来 返回 true;

再 回到AQS870行 运行 parkAndCheckInterrupt()  挂起当前线程

 

到现在lock方法结束;当遇到unpark方法后继续循环 再次尝试获取(tryAcquire(arg);成功后

释放 哨兵节点(第一个节点) 把当前节点 设置成head 作为哨兵节点.

 

继续看unlock方法 ReentrantLock中

 

AQS中:

tryRelease(arg) 尝试释放,在ReentrantLock中实现

因为当前持有锁 getState() = 1
int c = getState() - releases, 
set State = 0 
设置占有线程为null
retrun true;

返回AQS的release方法

lock()方法时候 h.waitStatus = -2 运行 unparkSuccessor(h);

head节点 状态小于0,设置为0,next 节点不为null,执行 LockSupport.unpark(s.thread) 唤醒;

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值