ReentrantLock学习(二)类整体结构及核心方法时序

一、整体结构

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不支持类的多集成) 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值