深入源码理解ReentrantLock锁

整体介绍

ReentrantLock是JUC自带的一种可重入锁

主要有两种锁形式

  • 公平锁
  • 非公平锁

主要功能有两种

  • 加锁
  • 释放锁

本质是AQS(同步等待队列),一个带头结点和尾结点的双向链表
当当前节点完成任务,会唤醒队列里面的下一个可唤醒节点
新的任务到来会放到队列的最后面,等待唤醒

AQS介绍

属性

AQS同步等待队列是一个带头尾节点地址的双向链表

重要几个属性

  • state
  • Node
  • head
  • tail
  • exclusiveOwnerThread

state

/**
 * 同步状态变量
 * 用于判断锁是否已经被线程持有
 * 当 state >= 1 表明前锁已经被线程持有
 * 如果是可重入锁每次重新进入state+1
 */ 
private volatile int state;

Node

AQS同步队列存的就是Node节点

Node {
   
    // 在同步队列中等待的线程等待超时或者被中断,取消继续等待
    static final int CANCELLED = 1;
    // 当前结点表示的线程在释放锁后需要唤醒后续节点的线程
    static final int SIGNAL = -1;

    //等待状态 
    //0-初始状态,激活状态
    //1-CANCELLED 取消
    //-1-SIGNAL 等待激活
    volatile int waitStatus;

    //前一个节点的地址
    volatile Node prev;

    //后一个节点的地址
    volatile Node next;

    //当前节点代表的线程
    volatile Thread thread;
}

head

//AQS队列的头结点
private transient volatile Node head;

tail

//AQS队列的尾结点
private transient volatile Node tail;

exclusiveOwnerThread

//当前持有该锁的线程
private transient Thread exclusiveOwnerThread;

ReentrantLock介绍

主要是讲非公平锁,因为用的最多,后面有时间会补充公平锁

ReentranLock通过构造器设置公平锁和非公平锁

public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

公平锁和非公平锁的类结构图
公平锁结构图
非公平锁

非公平锁

非公平锁有两个地方提现

  1. 新节点在Lock()时会先尝试获取锁
  2. 第一次尝试获取锁失败时,会加入到等待队列,这时候会判断是不是前一个节点是不是head节点,如果是的话,会再次尝试获取锁

加锁

1、调用AQS里面通用加锁逻辑

public void lock() {
   
   sync.acquire(1);
}

2、尝试获取锁或者加入到等待队列,否则中断当前线程

public final void acquire(int arg) {
   
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值