java面试必备八股文(Java多线程(6):锁与AQS(中))
您好 ,我是湘王 ,这是我的博客园 ,欢迎您来 ,欢迎您再来~
Java中的AQS(AbstractQueuedSynchronizer ,抽象队列同步器)是用来实现锁及其他同步功能组件的Java底层技术基础 ,java.util.concurrent包下大部分类的实现都离不开它 。
通过继承AQS:
1 、ReentrantLock的内部类实现了公平锁和非公平锁;
2 、CountDownLatch的内部类实现了发令枪;
3 、ReentrantReadWriteLock的内部类实现了独享锁和共享锁;
4 、Semaphore的内部类实现了公平锁和非公平锁 。
AQS主要实现两大功能:独占(Exclusive ,有时也叫排他)和共享(Share) 。
AQS在内部维护一个FIFO(First In First Out ,先进先出)的CLH(Craig ,Landin,and Hagersten)线程阻塞队列和一个资源同步状态的变量volatile int state 。
CLH是一个虚拟的双向队列 ,也就是不存在队列实例 ,仅存在节点之间的关联关系的队列 。AQS是将每一条请求共享资源的线程,封装成一个CLH线程队列节点(Node) ,从而实现锁的分配 。因此 ,说了一大堆,用一句简单的话来形容AQS就是:基于CLH线程阻塞队列 ,通过volatile变量 + CAS + 自旋方式来改变线程状态 ,成功则获取锁 ,失败则进入CLH队列 。
AQS已经实现了CLH线程阻塞队列的维护 ,所以一般子类自定义实现AQS ,要么是独占 ,要么是共享 ,也就是要么实现tryAcquire()和tryRelease()等系列方法 ,要么实现tryAcquireShared()和tryReleaseShared()等系列方法 。
CLH队列由多个node节点组成 ,而且大量使用“CAS自旋volatile变量 ”这种经典代码:
CLH队列的结构为:
给CLH设置首节点:
给CLH设置尾节点:
整个AQS的流程如图:
AQS特别复杂,如果想把多线程搞透的 ,就需要深入研究每个方法的流程 ,拿acquire(int)方法的执行流程为例:
我把AQS的源码做了较为详细的注释,可以结合注释看看 。例如:
如果只是了解多线程的简单用法 ,AQS可以绕过。
感谢您的大驾光临!咨询技术 、产品 、运营和管理相关问题 ,请关注后留言 。欢迎骚扰,不胜荣幸~
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!