谈谈对AQS的一些理解
AQS的概念
AQS全称AbstractQueuedSynchronizer,是java并发包中的核心类,诸如ReentrantLock,CountDownLatch等工具内部都使用了AQS去维护锁的获取与释放:
AQS内部结构
首先我们可以找到这样一张图:
它描述了其内部是如何维护线程的状态,以及锁的获取。类似于一个阻塞队列,当前持有锁的线程处于head(记住不是在阻塞队列中),新进来的无法获取到锁的线程则被包装成为一个Node节点依次放于队尾。
我们可以看到其内部几个核心的属性:
head:当前持有锁的线程
tail:阻塞队列中未获取到锁的线程
state:这是AQS里面最重要的一个变量,锁的获取与释放都与其密切相关。当它等于0时,表示没有线程持有锁,当大于0(锁可重入,每次获取锁,state加1)时表示有线程持有锁。
再看看线程时如何进行包装,然后放于阻塞队列的:
每一个线程都会被包装称为一个Node节点存储于阻塞队列中,SHARED和EXCLUSIVE分别指当前线程是期望获取共享锁,还是独占锁。
waitSatus:当大于0时表示当前线程放弃了争取锁。
prev:前一个节点
next:后一个节点
thread:所封装着的线程
内部实现
AQS通过以下方法去控制锁的获取和释放:
acquire(int arg):用于获取独占锁
很简单,首先尝试获取锁,如果获取失败,说明有线程持有锁,则将其加入当等待队列的末尾。
release(int arg):用于释放独占锁
如果当前线程不为空,且后面有等待的线程,则唤醒后序线程获取锁。
acquireShared(int arg):
不多说,即用于获取共享锁。
tryReleaseShared(int arg):
用于释放共享锁
总结
AQS内部通过一个CLH阻塞队列去维持线程的状态,并且使用LockSupport工具去实现线程的阻塞和和唤醒,同时里面大量运用了无锁的CAS算法去实现锁的获取和释放。今后再继续分享具体的并发包里面是如何通过AQS去实现更多丰富的并发工具。
————————————————
版权声明:本文为CSDN博主「呛水鱼」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/jackFXX/article/details/81104871
最新文章
- python下编译py成pyc和pyo
- 免费素材:包含 250+ 组件的 DO UI Kit
- ESI 动态缓存技术
- RDIFramework.NET ━ 9.4 角色管理 ━ Web部分
- Android SDK Manager更新不了的解决办法
- SAE J2534 Pass-Thru API
- STC89C52RC片内资源介绍
- WdatePicker时间控件联动选择
- volatile的理解和使用
- [python]使用django快速生成自己的博客小站,含详细部署方法
- Android Wear开发
- hadoop家族技能图谱
- numpy中pad函数的常用方法
- netty源码解解析(4.0)-9 ChannelPipleline的默认实现-链表管理
- Application生命周期
- 并发的HTTP请求,apache是如何响应的,以及如何调用php文件的
- Windows Pre-commit hook for comment length Subversion
- JDK 和 JRE 有什么区别
- php利用root权限执行shell脚本 (转)
- POJ 1389 Area of Simple Polygons 扫描线+线段树面积并