AQS源码探究之竞争锁资源

本文通过分析ReentrantLock的源码,探讨AQS的竞争锁资源、线程释放锁的流程,以及公平锁和非公平锁的区别。在非公平锁中,线程获取和释放锁的细节被详细阐述,包括节点状态管理和阻塞链表的运作。公平锁则会在释放锁后,允许阻塞队列中最前面的线程获取锁资源。通过DEBUG例子,进一步理解AQS的工作原理。
摘要由CSDN通过智能技术生成

我们进入ReentrantLock源码中查看其内部类

  • Sync 对AQS进行扩展公共方法并定义抽象方法的抽象类
  • FaireSync 实现公平锁的AQS的实现类
  • UnFairSync 实现非公平锁的ASQ的实现类

我使用例子进行的debug,然后一步一步看源码。例子在文章最后面

以下流程皆以非公平锁为例

线程竞争锁资源

AQS的state解释:

  • 0 表示锁没有被占用
  • 1 表示锁被占用了
  • > 1 表示锁被重入了 PS: ReentrantLock是可重入锁

获得锁执行流程

  1. 创建ReentrantLock对象
// ReetrantLock 默认创建一个非公平锁的AQS
public ReentrantLock() {
    sync = new NonfairSync();
}
  1. 然后我们调用lock方法请求锁
    • 成功,即将锁的owner主人设置为当前线程,接下来就是回到线程中执行线程的任务。
    • 失败,即进入acquire的流程。
static final class NonfairSync extends Sync {
    
    final void lock() {
        // 请求锁资源,如果将锁的state状态0改成1,即为成功获得锁资源
        if (compareAndSetState(0, 1))
            // 将锁的拥有者设置为当前线程,里面就一句话没啥好看的
            setExclusiveOwnerThread(Thread.currentThread());
        else
            acquire(1);
    }
    
}

下面是AQS阻塞链表是由一个双向链表组成的。

阻塞链表的成员对象Node的waitState状态解释:

  • CANCELLED = 1 表示线程已经被取消了
  • SIGNAL = -1 表示后继线程需要unpark解除阻塞,下图即表示。

锁竞争失败流程

  1. 进入acquire方法
public final void acquire(int arg) {
	// 首先再次请求锁
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}
  1. 首先会执行tryAcquire方法
protected final boolean tryAcquire(int acquires) { // 注意:我们进入的是非公平锁的tryAcquire实现
    return nonfairTryAcquire(acquires);  
}

再次进入nonfairTryAcquire(acquires)方法

final boolean nonfairTryAcqu
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值