ReentrantLock 源码流程分析 公平锁和非公平锁的区别

ReentrantLock

公平锁

  1. 尝试加锁 tryAcquire(arg)
    1. 查看state是否是0 也就是是否是自由状态
      1. 如果是0 先看是否有队列的存在 hasQueuedPredecessors或队列中是否有线程排队 如果队列是空(无队列的情况)那么就继续compareAndSetState(CAS)如果是此时是state还是0那么就setExclusiveOwnerThread(current); 加锁成功直接 return true
      2. 如果不是自由状态查看当前拿到锁的线程是否和当前线程相同 相同则返回true
      3. state 不为0且当前持有锁的线程不是自己 或state=0 但是队列中有人 返回 false
      4. Note:如果tryAcquire(arg) 成功则直接返回了不需要任何其他的操作与队列无关,此时的队列仍然是空的,head 和tail都是null
  2. 如果尝试加锁失败 tryAcquire(arg) 失败则需要执行acquireQueued(addWaiter(Node.EXCLUSIVE), arg)
    1. addWaiter(Node.EXCLUSIVE) 返回的是包含有当前Thread的新node
      1. 如果这个AQS队列是空的那么需要进行对队列的初始化enq(node);也就是先将头节点和尾节点,指向一个new node里面的成员变量都是null,然后再将当前的node(里面包含有Thread)的prev指向空node,然后让tail指向自己,然后空node的next指向自己。
      2. 如果这个队列不为空,那么就是直接把自己加入到尾节点中,排队排在队尾
    2. 此时会真正的进入acquireQueued函数
      1. 首先判断是否自己的前一个节点是刚才说的空node如果是就说明自己排在第二个,下一个就是自己,因此他可以自旋一次,再次尝试加锁tryAcquire(arg) 大部分都是失败的
      2. 失败则直接park 阻塞这个线程(调用的是操作系统的函数)

非公平锁

  1. 首先与公平锁不同的一点是他直接去进行compareAndSetState(CAS)在公平锁中他需要先判断state是否是0(判断锁是否是自由状态)且会判断队列是否为空,队列中是否有其他线程在排队。
    1. 而非公平锁在第一步就直接去判断是否锁是空闲的,如果空闲就插队,然后占有锁然后返回
    2. 如果此时无法占有锁,那么执行acquire(1);
    3. 执行nonfair的 tryAcquire(arg)
    4. 这是fair和nonfair的tryAcquire(arg)
    5. 在我看来这里唯一的区别就是:是否有查看队列存在或这队列是否有线程在等待
    6. 在非公平锁中会先查看state的状态(锁是否是自由的)
      1. 如果不自由那么park
      2. 如果是自由状态那就尝试插队获取锁(不会去查看队列)。如果获取失败那就park

非公平锁
请添加图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值