java学习|图说多线程(四)通过Semaphore看AQS

今天和大家一起聊一聊AQS,

对于这个通用的同步器队列,

如果直接拿源码看的话,

是能看到方法的意思和对队列的各种操作,

但是感觉这样是一个没有灵魂的AQS,

上文说到Countdownlatch , ReentrantLock,Semphore都是基于AQS,就笔者感觉,日常Countdownlatch , ReentrantLock使用超过了Semaphore , 本着雨露均沾,我们今天通过Semaphore来看看AQS。

Semaphore:

对于Semaphore的理解和使用,我们参考Semaphore源代码的说明:

可以看到, 其核心的方法是 acquire(); 和 release();初始化时先初始化一个permits数量,调用accquire时会使permits减1 , 调用release时会使permits加1, 同样,accquire和release操作都是委托给AQS。

从上文借一张AQS的图,下面我们就跟着源码中的示例说明看下是怎么调用AQS的。

首选是Semaphore的构造函数。

我们传给Semaphore的permits被传给了AQS的构造器,根据fair去构造一个公平锁/非公平锁。示例代码构造了一个公平锁。跟踪源代码可以看到,最终是调用了Sync的setState方法,将传入的permits最终设置到了AQS的state值。

我们可以猜测,acquire和release应该都是对这个state进行判断和操作。

acquire()方法:

在调用acquire方法时,虽然我们没有传值,但实际上jdk默认帮我们传了1,也就是每次操作state只做加1或减1操作。继续跟踪acquire方法可以看到最终是调用了AQS的doAcquireSharedInterruptibly

1026: 向队列中添加一个节点,并获取到其引用node 。

1028: 不断尝试获取到node的前面一个节点p

1030: 如果p是头节点,开始尝试获取获取许可证,对Semaphore来说,就是操作AQS中的 state减1.

这里tryAcquireShared在Semaphore中被重写:

可以看到在251行,如果node前还有节点,则返回-1 。 就是要等节点p运行完,然后p.next=null. 释放p的引用,让p处于GCRoots不可达的状态,然后被GC回收。

如果获取失败,则入队,需不需要抛出中断, 需要则抛出一个中断异常,不需要,则进行下一次的尝试,直到获取成功 return; 

总结:以上分析是基于公平锁进行的AQS分析,关于非公平锁的实现,有兴趣的小伙伴可以跟踪源码看下,期实比公平锁就多了一步, 来了不排队,先直接询问,我能不能获取到锁,能获取到,就直接获取,获取不到再老老实实排队去。

—END—

前期回顾:

Java学习|图说String(一):String的存储方式

java学习|图说String(二):基于byte数组的String方法调用

java学习|图说String(三)String中'+'和StringBuilder的区别

QQ群:661749608

微信群请点击公众号菜单进微信群

我们哦~

文字: 微笑的小小刀

排版:花音

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值