一、整体结构
ReentrantLock的核心实际为 AbstractOwnableSynchronizer,简称AQS
- Lock:锁接口类,定义了锁的一些基本方法
- ReentrantLock:其锁的实现依赖于内部sync
- Sync:ReentrantLock的内部类,继承了AQS,实现了部分模板方法
- NonfairSync:ReentrantLock的内部类,继承了Sync,ReentrantLock非公平锁的实现,也是默认ReentrantLock的默认锁
- FairSync:ReentrantLock的内部类,也继承了Sync,ReentrantLock公平锁的实现,构造时需传入参数true进行创
- AbstractOwnableSynchronizer:主要提供记录持有锁线程的方法
- AbstractQueuedSynchronizer:简称AQS,提供了一个同步器队列链表,同步状态以及一系列模板方法,如tryAcquire、tryRelease、tryAcquireShared、tryReleaseShared、isHeldExclusively等
- Node:AQS内部类,链表
- Condition:定义了Condition的相关方法,如await、signal
- ConditionObject:AQS内部类,实现了Condition接口,内部维护了一个等待队列链表
- LockSupport:提供了park、unpark等方法,来挂起、唤醒线程(下图未体现是因为该类提供的静态方法)
二、核心方法时序
下图是以ReentrantLock的非公平锁为例,与整体与公平锁相差不是很多。
ps:内部方法解析之后文章分析
三、个人思考
Condition 与 Lock是如何建立联系的?为什么Condition可以使锁挂起,可以唤醒锁?
其中,有个类结构比较巧妙
以AQS为核心,ConditionObject为AQS的内部类,且实现了Condition接口,那么由ConditionObject构造的Condition对象,则可以使用AQS的方法及属性,而ReentrantLock的核心是内部持有一个Sync的对象,而这个Sync的类继承了AQS,锁功能的实现依赖于AQS内部的状态及链表的记录,那么Condition则可以调用使用其外部类(AQS)的属性(链表及状态)以及方法(本身的方法及子类实现的方法)来控制当前锁线程的挂起及唤醒。
内部类对象的创建需要起外部类对象进行调用,创建出来的内部类对象持有外部类对象的引用,这样再加上java的继承,就可以建立看似不太相关的两个类,其实已经建立了联系。(其实对于一些大神来说,这个用法不算啥,但本人理解这块稍稍花了些时间,特此记录一下)
例如
//内部类的interface,类似于Condition
public interface Inner {
int getValue();
void add(int value);
}
//外部类的抽象类,含一内部类InnerImpl,类似以AQS
public abstract class Father {
protected int value;
class InnerImpl implements Inner {
@Override
public int getValue() {
return value;
}
@Override
public void add(int v) {
value+=v;
}
}
}
//外部类的具体实现,集成了外部类的抽象类,类似于ReentrantLock.Sync
public class Outer extends Father {
Outer(int value) {
this.value = value;
}
public Outer(){
this.value = 0;
}
Inner getInner(){
return new InnerImpl();
}
public int getValue(){
return this.value;
}
public void setValue(int v){
this.value = v;
}
}
//main方法
public static void main(String[] args) {
//构建outer,并设置值
Outer outer = new Outer(111111);
//通过outer创建inner
Inner inner = outer.getInner();
//inner获取值
System.out.println(inner.getValue());
//outer重设值
outer.setValue(1);
//inner获取值
System.out.println(inner.getValue());
//inner修改值
inner.add(10);
outer获取值
System.out.println(outer.getValue());
}
执行结果
111111
1
11
可以看到,双方在Father内部建立了两个对象的联系,也就是变相实现“双继承”的方式(java不支持类的多集成)