java 中的锁 aqs_带你看看Java-AQS同步器 源码解读<三>共享锁

0fefb7d64ce3a208a556b243fdafab0d.png

共享锁

前面2篇文章描述了AQS中独占锁的加锁解锁,那今篇文章我们聊下AQS 中分享锁的加锁解锁 既然说道共享锁和独占锁,那2者最本质的区别是什么呢,大家应该记得AQS中有一个同步器状态State 字段,其实说说白了共享模式和独占模式,就是同步器的状态是否允许被多个线程所获取,比如我们之前说的ReentrantLock就是独占锁的模式,因为同步器状态只能被一个线程所获取,那这篇我将使用Semaphore来做分析共享锁。

共享锁加锁

Semaphore初始化

上面是信号量的默认构造函数 默认实现的是非公平锁

我们看到我们传递的信号量permits 最终还是调用了Sync的构造函数

setState 其实就是调用AQS中的方法 就是给State 赋值

Semaphore获取 acquire() 方法

选取一个默认的获取方法如下:

可以看到 我们这边默认获取的信号量是1,当然acquire也有带参数的构造方法 很明显 我们看到acquire默认的构造函数调的是Sync中acquireSharedInterruptibly方法 之前我也说过Sync是继承了AQS的 我们IDE跟进这个方法 就进入了AQS类中

进入AQS中acquireSharedInterruptibly方法

重写tryAcquireShared的实现

看了上面的代码,我们有看到一个熟悉的方法tryAcquireShared和之前独占锁tryAcquire很像,这个方法也是需要子类去重写的,熟悉的套路,熟悉的味道,哈哈!那我们就去找下tryAcquireShared这个方法 找下找 很快我找到了 在NonfairSync里面找到了 代码上面也有,NonfairSync非公平锁的tryAcquireShared方法原来是调用的父类的方法也就是Sync的,那我就去Sync类中看一看,果然找到了

看到这个返回我很懵逼呀,怎么就返回了呢,那我们结合刚才上面的acquireSharedInterruptibly来看 原来他判断如果返回值小于0 就会执行下面的方法doAcquireSharedInterruptibly方法,翻译成白话文 就是 就是 同步器里面5个苹果,可能前面几个线程都把苹果拿了 我再来拿的时候发现小于0了,拿怎么办呢 ,只能去排队等待咯,和独占锁流程差不多,区别就是这个后面,好的 我们慢慢再开看,

doAcquireSharedInterruptibly 获取失败后排队

setHeadAndPropagate方法

doReleaseShared方法

这个条件是自旋唯一的出口就是head 没有发送变化 说明没有后面的线程获取资源 那就退出自旋,如果head发生了变化 说明传播的有效果了 后面线程获取到到了资源 还有要注意的地方 是doReleaseShared这个方法有2个地方调用 一个是就是这边共享锁加锁 还有一个就是共享锁解锁的地方

共享锁解锁

我们看下共享锁的解锁 其实看完了上面的内容 这个就简单了很多

Semaphore获取 releaseShared() 方法

看到doReleaseShared 我们应该很熟悉了 刚才加锁的时候 也用到了这个方法 具体就不多说了

总结共享锁和独占锁 区别之处

看了共享锁的加锁 我们在回顾下独占锁加锁 这边的处理,不然想到 这边的区别就是head获取资源后 独占锁直接设置自己为head 然后返回 而共享锁这边head 获取资源后 如果资源状态还有剩余 就会唤醒其余线程去获取,这就是2者的区别 同样的解锁的过程也是几乎一样 底层唤醒线程的unparkSuccessor方法都是公用的,解锁的过程也是多一个唤醒传播的过程

好的AQS的同步队列 的共享模式和独占模式 用了前面的3篇文章 和大家分享完了 后面 会分析下AQS中的条件队列 具体怎么运行的~ 不要吝啬你的点赞 ,点赞 给我东西 ,继续写作

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值