基于AQS的锁
锁分为独占锁和共享锁,它们的主要实现都是依靠AbstractQueuedSynchronizer,这个类只提供一系列公共的方法,让子类来调用。基于我了解不深,从这个类的属性,方法,和独占锁的获取方式去了解这个类。
AbstractQueuedSynchronizer的主要属性和方法:
| 属性/方法 | 含 义 |
| Thread exclusiveOwnerThread | 这个是AQS父类AbstractOwnableSynchronizer的属性,表示独占模式同步器的当前拥有者 |
| Node | 上面已经介绍过了,FIFO队列的基本单位 |
| Node head | FIFO队列中的头Node |
| Node tail | FIFO队列中的尾Node |
| int state | 同步状态,0表示未锁 |
| int getState() | 获取同步状态 |
| setState(int newState) | 设置同步状态 |
| boolean compareAndSetState(int expect, int update) | 利用CAS进行State的设置 |
| long spinForTimeoutThreshold = 1000L | 线程自旋等待的时间 |
| Node enq(final Node node) | 插入一个Node到FIFO队列中 |
| Node addWaiter(Node mode) | 为当前线程和指定模式创建并扩充一个等待队列 |
| void setHead(Node node) | 设置队列的头Node |
| void unparkSuccessor(Node node) | 如果存在的话,唤起Node持有的线程 |
| void doReleaseShared() | 共享模式下做释放锁的动作 |
| void cancelAcquire(Node node) | 取消正在进行的Node获取锁的尝试 |
| boolean shouldParkAfterFailedAcquire(Node pred, Node node) | 在尝试获取锁失败后是否应该禁用当前线程并等待 |
| void selfInterrupt() | 中断当前线程本身 |
| boolean parkAndCheckInterrupt() | 禁用当前线程进入等待状态并中断线程本身 |
| boolean acquireQueued(final Node node, int arg) | 队列中的线程获取锁 |
| tryAcquire(int arg) | 尝试获得锁(由AQS的子类实现它) |
| tryRelease(int arg) | 尝试释放锁(由AQS的子类实现它) |
| isHeldExclusively() | 是否独自持有锁 |
| acquire(int arg) | 获取锁 |
| release(int arg) | 释放锁 |
| compareAndSetHead(Node update) | 利用CAS设置头Node |
| compareAndSetTail(Node expect, Node update) | 利用CAS设置尾Node |
| compareAndSetWaitStatus(Node node, int expect, int update) | 利用CAS设置某个Node中的等待状态 |
可以看出这个类是一个链表结构,拥有head和tail,next,它的同步状态是通过int类型 state来表示的,0表示未获取,1表示获取,大于1表示重入数,compareAndSetState(int expect,int update)和spinForTimeoutThreshold是在多线程下插入节点到队列时保证快速和唯一正确的。compareAndSetState 和 setState 都是设置state的值,可以看源代码,发现compareAndSetState主要是获得锁,多线程竞争的时候使用,而setState则在锁重入的时候使用,有偏向锁的作用。
AQS是一个基于FIFO的队列的实现,有一个Node的内部类,主要属性如下如下:
| 属 性 | 定 义 |
| Node SHARED = new Node() | 表示Node处于共享模式 |
| Node EXCLUSIVE = null | 表示Node处于独占模式 |
| int CANCELLED = 1 | 因为超时或者中断,Node被设置为取消状态,被取消的Node不应该去竞争锁,只能保持取消状态不变,不能转换为其他状态,处于这种状态的Node会被踢出队列,被GC回收 |
| int SIGNAL = -1 | 表示这个Node的继任Node被阻塞了,到时需要通知它 |
| int CONDITION = -2 | 表示这个Node在条件队列中,因为等待某个条件而被阻塞 |
| int PROPAGATE = -3 | 使用在共享模式头Node有可能处于这种状态, 表示锁的下一次获取可以无条件传播 |
| int waitStatus | 0,新Node会处于这种状态 |
| Node prev | 队列中某个Node的前驱Node |
| Node next | 队列中某个Node的后继Node |
| Thread thread | 这个Node持有的线程,表示等待锁的线程 |
| Node nextWaiter | 表示下一个等待condition的Node |
获取独占锁的状态示意图如下:

基于AQS的锁的更多相关文章
- canal源码之BooleanMutex(基于AQS中共享锁实现)
在看canal源码时发现一个有趣的锁实现--BooleanMutex 这个锁在canal里面多处用到,相当于一个开关,比如系统初始化/授权控制,没权限时阻塞等待,有权限时所有线程都可以快速通过 先看它 ...
- JAVA并发-基于AQS实现自己的显示锁
一.了解什么是AQS 原文链接:http://www.studyshare.cn/blog-front/blog/details/1131 AQS是AbstractQueuedSynchronizer ...
- 老板让只懂Java基本语法的我,基于AQS实现一个锁
10 点整,我到了公司,又成为全组最后一个到的员工. 正准备刷刷手机摸摸鱼,看见老板神秘兮兮地走了过来. 老板:闪客呀,你写个工具,基于 AQS 实现一个锁,给咱们组其他开发用 我:哦好的 老板:你多 ...
- 聊聊ReentrantLock基于AQS的公平锁和非公平锁的实现区别
ReentrantLock锁的实现是基于AQS实现的,所以先简单说下AQS: AQS是AbstractQueuedSynchronizer缩写,顾名思义:抽象的队列同步器,它是JUC里面许多同步工具类 ...
- ReentrantLock是如何基于AQS实现的
ReentrantLock是一个可重入的互斥锁,基于AQS实现,它具有与使用 synchronized 方法和语句相同的一些基本行为和语义,但功能更强大. lock和unlock ReentrantL ...
- 基于AQS实现的Java并发工具类
本文主要介绍一下基于AQS实现的Java并发工具类的作用,然后简单谈一下该工具类的实现原理.其实都是AQS的相关知识,只不过在AQS上包装了一下而已.本文也是基于您在有AQS的相关知识基础上,进行讲解 ...
- RedLock.Net - 基于Redis分布式锁的开源实现
工作中,经常会遇到分布式环境中资源访问冲突问题,比如商城的库存数量处理,或者某个事件的原子性操作,都需要确保某个时间段内只有一个线程在访问或处理资源. 因此现在网上也有很多的分布式锁的解决方案,有数据 ...
- 关于AQS——独占锁的相关方法(一)
一.序言 Lock接口是juc包下一个非常好用的锁,其方便和强大的功能让他成为synchronized的一个很好的替代品. 我们常用的一个Lock的实现类(好像也是唯一一个只实现了Lock接口的类) ...
- 如何基于String实现锁?
在某些时候,我们可能想基于字符串做一些事情,比如:针对同一用户的并发同步操作,使用锁字符串的方式实现比较合理.因为只有在相同字符串的情况下,并发操作才是不被允许的. 因为String 类型的变量赋值是 ...
随机推荐
- linux tar
转自:http://www.cnblogs.com/qq78292959/archive/2011/07/06/2099427.html tar -c: 建立压缩档案-x:解压-t:查看内容-r:向压 ...
- 关于使用TP-Link桥接小米路由器
家里因为有个小卧室,小卧室的写字台上面放了一台台式电脑,而我又不想用台式电脑牵一条长线到客厅的网口或者路由器上面,因为太麻烦,所以我使用了TPLink的无线USB插在了我的主机USB上,略去TPLIN ...
- NHibernate Demo 和 效率测试
本文关于NHibernate的Demo和效率测试,希望对大家有用. 1.先去官网下载Nhibernate 2.放入到项目中并建立Helper类 private static ISession _Ses ...
- OAF_开发系列22_实现OAF条形码BarCode
20150717 Created By BaoXinjian
- Oracle补习班第四天
Everything has its time and that time must be watched. 万物皆有时,时来不可失 1,管理参数文件 参数文件分两种spfile二进制文件和pfile ...
- Android屏幕适配全攻略 (转载)
http://blog.csdn.net/jdsjlzx/article/details/45891551 https://github.com/hongyangAndroid/AndroidAuto ...
- 用直接路径(direct-path)insert提升性能的两种方法
1.传统串行insert方式 常见的insert方式有两种: (1) insert into table_name values(....) (2) insert into target_table ...
- cctype头文件中的一些内容
1. string 标准库 1.1初始化 string s1; 默认构造函数s1为空 string s2(s1); 将s2初始化为s1的一个副本 string s3(“value”); 将s3初始化为 ...
- java知识点
一.面向对象的五大基本原则: 1.单一职责原则(Single-Resposibility Principle):一个类,最好只做一件事,只有一个引起它的变化.单一职责原则可以看做是低耦合.高内聚在面向 ...
- jquery 获取鼠标和元素的坐标点
获取当前鼠标相对img元素的坐标 $('img').mousemove(function(e) { varpositionX=e.pageX-$(this).offset().left; //获取当前 ...