java aqs_Java - AQS 扫盲笔记

最近真的是对Java中的基础思想狠下功夫,因为面试一线大厂,这种基础简直是必问。上一节讲过CAS,这回我们来看AQS。

1、学习思路:从非公平锁进入源码,可以看到Sync extends AbstractQueuedSynchronizer,这个AbstractQueuedSynchronizer就是AQS。

2、有CAS还不够吗,为什么设计AQS?

CAS 只是保证原子性。而AQS却能保证并发线程的有序且安全。

Java作者是想把AQS做成并发编程的基础组件。显示锁、读写锁的源码中都有AQS,线程池中的Worker也使用了AQS。所以记住:AQS是并发编程中很基础很基础的组件。

3、理解AQS前,先了解下LockSupport和CLH队列锁

(1)LockSupport:提供了线程的阻塞和唤醒功能。是构建AQS组件的基础工具。

(2)CLH队列锁:一种思想。尝试获取锁的多个线程,当一个线程获取到锁,那么其他的线程要等待,这些等待的线程会被放入一个列表,如图所示:

dcd3d485e6061d883e762ed72ec887d8.png

每一个线程都会被包装成这样的一个节点:前驱节点的引用和当前节点的lock状态。

新来的线程会放到队列/链表尾部,新线程将自己包装成一个节点,节点中包含自身锁的状态和前驱节点的引用,而且线程节点一直在这个前驱节点的引用上一直自旋(监控),看前驱节点的lock状态是否改变,前驱借钱锁释放了,就会locked变为false。后面的节点监测到这个就会改状态。

4、真正了解AQS

AQS 是面向锁的开发者的,像我们平时要用到锁时直接使用Lock就好了,不会去再实现AQS。也就是说AQS时锁的源码中的思想,太底层了。

AQS是抽象类,里面几个方法没有实现,这是用了模板方法模式,这些实现放到子类中去实现。

对于锁,它是有状态的,必须有一个标志位来标志,而AQS中是使用了一个volatile int state表示,volatile保证线程间的可见性,所以其他等待的线程可以见到这个锁标志,AQS又用CAS通过对这个标志状态 由0 变1来完成锁获取锁释放的变化,保证了state的线程安全。这个标志叫state,非常重要的变量。

5、总结

AQS的数据结构:链表 + 状态标志

AQS = CLH队列锁 + CAS:

CLH队列锁:阻塞线程排队

CAS:保证锁的线程安全

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值