目录可重读锁有两种实现方法。 1、AbstractQueuedSynchronizer源代码分析1、继承关系2、构造函数3、属性2、ReentrantLock源代码分析1、继承关系2、构造函数3、属性和内部类同步
重新锁定有两种实现方法。
1、公平锁:先来后到,先抢锁线程先执行;
2、公平锁:你先来再来,谁抢谁先执行;
这两个锁的实现都用于一个名为AbstractQueuedSynchronizer的类(简称AQS,实现锁的重要类),该类基于FIFO队列,在锁和其他相关同步设备的基础框架中由于该同步器(以下简称同步器)使用int来表示状态,因此要了解ReentrantLock (可重新锁定的实现原理),必须先了解AQS,所以先看看AQS的实现:
一、AbstractQueuedSynchronizer源代码解析1、继承关系
2、构造函数
3、属性顺便还分析了属性相关的内部类:
AQS状态:
state=0表示锁定处于空闲状态
state0表示锁定已被占用
状态0表示溢出
那么,要知道这些基本属性和方法就好了。 解析ReentrantLock源代码时将调用其他AQS方法。
让我们看看ReentrantLock的源代码。
二、ReentrantLock源代码解析1、继承关系
2、构造函数
3、属性和内部类Sync类源代码(公平锁和非公平锁的父类) :
从NonfairSync (非公平性锁定源代码: lock ) )方法看:
NonFairSync获取锁定的过程总结如下:
1、第一次通过CAS强制抢锁,想抢锁失败就再次抢锁;
2、第二次尝试抢锁,首先判断锁是否被占用,如果state=0,直接通过CAS获取锁,
如果获取成功,请更正state,将当前线程计数为AQS,然后返回正常; 如果确定锁已被占用,如果占用锁的线程是当前线程,则直接修改state并返回正常;
以上都不满意:
将当前线程添加到存储线程的双向链表中(如果当前双向链表为空,则初始化头部节点。 头部节点是空节点,没有任何内容。 然后,将存储当前线程的节点添加到链表之后,并更新链表的末尾指针。) ),
尝试获取锁定(对新添加的节点进行排队后,该节点有两种状态:获取锁定或挂起锁定,如果该节点不是头节点的下一个节点,则检查该节点是否应该挂起) 如果当前节点的前驱节点不是头节点,则前驱节点会通知您,并且他可以放心地锁定。 如果当前节点的前体节点是头部节点,则尝试在tryAcquire中获取锁定直到成功;如果成功获取锁定,则使当前节点成为头部节点。)。
从lock )方法查看FairSync (公平性锁定)源代码。
总结FairSync获取锁定的过程。
1、尝试获取锁定
如果锁定未被占用,则确定当前线程是否满足条件(AQS队列为空或当前线程位于AQS队列的开头),修改state以将当前线程记录在锁定中,然后返回正常
如果锁定已被占用,且当前线程占用了锁定,请更正state并返回正常
如果以上得不到满足,就会失败并返回;
2、未能锁定时,将线程添加到AQS队列中;
可重新调整的锁包括ConditionObject。 这是Condition接口的唯一实现类,Condition提供了比wait、notify和notifyAll更灵活的线程间通信机制,并分析源代码。
最后是unlock (谈谈方法:
4、方法其他方法比较简单,以下介绍ReentrantLock类的其他方法。
方法查询int getHoldCount )、当前线程保持此锁定的次数(即lock )以及调用方法的次数。 int getQueueLength ) )返回等待获取此锁定的估计线程数。 集成队列长度(condition condition )返回与此锁定相关的条款和条件的线程估计数。 booleanhasqueuedthread (thread thread )、boolean hasQueuedThreads )查询显示: 指定当前线程是否正在等待获取此锁定布尔条件约束(boolean isFair )查询;如果是公平锁定,则为true(reentrantlock为默认锁定) isLocked ) )确定查询中是否有线程保留此锁定。 lockInterruptbly ()在当前线程未中断时获取锁定; 如果被中断,则抛出(“异常”(InterruptedException ) tryLock ) )并尝试获取锁定。 如果锁定不在另一个线程中,则获取该锁定。 也就是说,成功获取并返回true。 否则,获取false (锁已获取到另一个线程) trylock (trylock ) longtimeout,如果timm锁不在另一个线程中,则获取该锁,即获取成功并返回true,并且未获取该锁区别:
非公平锁获得两次锁;