一个特别牛叉的方法

大家好,我是江湖人送外号[道格牙]的子牙老师。

不论你觉得是否牛叉,反正我觉得很牛叉。真正理解后我很赞赏道格李的代码功底。

国际惯例,先上代码
在这里插入图片描述
这个方法应该把很多人看懵了,来解析下。如果你对AQS的队列机制还不了解,记住一句话就可以了:AQS中的队列与我们正常写的队列不太一样,它的第一个节点是当前占有锁的线程对应的Node。我也认真想过道格李为什么要这样实现、为什么第一个节点不是待唤醒的线程对应的Node……因为我自己实现的AQS就是这个思路,也没发现有啥问题。所以这个问题只有道格李本人才能给出了,也或者只是个人习惯。

其实这个方法是非常精髓的,逻辑非常严谨。这边也教给大家一个分析问题的办法:如果有些代码你看不懂的时候,你就问问自己如果是我来实现我会怎么写?或者干脆自己动手写写看。其实在想在做的过程中,对比着看,答案自现。其实精简的代码都是从冗杂的代码中抽象出来的,抽象能力的高低是评估Coder水平的很关键的能力。

这个方法也是一样,如果想看懂,得把可能出现的场景想出来,即什么情况可以尝试加锁:
1、队列未初始化
2、队列中只有两个节点
3、队列中有两个以上节点且来抢锁的是队列中的第二个节点

接下来配合图详细讲讲。

队列未初始化

如果队列没初始化,说明队列的head属性、tail属性都是null,道格李通过h != t解决了这个情况。这种情况太简单,就不画图了。

如果是这种情况,h != t返回false,程序结束。

方法返回false,尝试加锁

队列中只有两个节点

这个场景是怎么产生的呢?有一个线程正在占用锁,这时候再来一个线程就会出现这个场景。因为队列中第一个Node对应的是当前占用锁的线程,后面进来的线程就会被封装成一个新的Node放入队尾。这块代码道格李在实现的时候也是非常精髓的。看图。
在这里插入图片描述

如果是这种情况:
h != t:因为还有两个节点,所以这里返回true,程序继续往后走
(s = h.next) == null:因为还有两个节点,所以这里返回false,程序继续往后走
s.thread != Thread.currentThread():这里肯定是相等的,所以这里返回false

方法返回false,尝试加锁

队列中有两个以上节点

这种情况应该是很多人在写代码的时候最容易忽略的。当然也包括我。
在这里插入图片描述
看人家道格李是如何解决的:
h != t:因为还有两个以上节点,所以这里返回true,程序继续往后走
(s = h.next) == null:因为还有两个以上节点,所以这里返回false,程序继续往后走
s.thread != Thread.currentThread():核心在这个判断,如果当前线程不是第二个Node对应的线程,返回true,方法返回true,不尝试加锁。如果当前线程是第二个Node对应的线程,返回false,方法返回false,尝试加锁

队列中只剩一个节点

可能有的同学就想不通了,什么情况下队列中会只剩一个节点呢?

答案就是队列中的所有Node对应的线程都已被唤醒且已执行完成,当前占有锁的线程是队列中最后一个Node。

这种情况不会来抢占锁,这边只是考虑到有的同学钻牛角尖会想到这种情况又不知道正确答案是什么样的,拓展一下。

进阶

如果你想学好JUC包,我并不建议你看Java领域的书籍,JUC包离真正的线程被封装了好几层。我倒建议你看看《Unix高级环境编程》,搞清楚操作系统层线程的本质。学东西要学本质,不要盯着那些花里胡哨的东西,这些东西,学得再多依然很菜。

关于AQS还有很多很多细节:比如waitStatue、state、自旋机制为什么是那样的、各种锁……,后面慢慢写文章分享。建议有能力的同学自己去研究去琢磨,不要奉行拿来主义。

道格李的代码可以说写得非常精简非常严谨,如果是你,会怎么实现呢?动手写写看吧。what?想看我写的?皮?

结语

韩愈说:师者,所以传道受业解惑也。我觉得还应该加上一层:开悟。传道受业解惑教的是知识本身,是结论,不能带来接收者的思考力。开悟即把你是如何分析问题、补了哪些前置知识、思考了哪些核心问题……把这个过程中在教学过程中模拟出来,启发学员自己去GET到结论,这样才有可能带出来青出于蓝而胜于蓝的学生。

成为一个老师很简单,但是成为一个好老师很难。这就是教育不公平的本质所在。子牙老师的并发课程会陆续公布,不学就亏大发了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值