AQS笔记

ReentrantLock是Java中的一种可重入锁,它基于AQS(AbstractQueuedSynchronizer)实现。AQS是一个核心的抽象类,用于构建锁和其他同步组件,通过一个int状态字段和FIFO等待队列管理资源的获取与释放。当加锁失败时,线程会被加入到等待队列,通过CAS操作保证线程安全。在解锁时,AQS会尝试唤醒等待队列中的下一个节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

比如ReentrantLock包含了AQS,内核中的锁机制实现都是依赖AQS组件的

//先来看看ReentrantLock内部怎么用AQS的
public class ReentrantLock implements Lock, java.io.Serializable {
    private static final long serialVersionUID = 7373984872572414699L;//序列化标识
    private final Sync sync;  //用这个来继承AQS,实现基于state状态和队列来实现加锁与解锁
    abstract static class Sync extends AbstractQueuedSynchronizer { /*略*/ }
    //加锁方法继承了Sync的子类来实现,空参构造里面创建的就是这个
      static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;
        final void lock() { //加锁方法
            if (compareAndSetState(0, 1))//使用CAS来尝试加锁:就是当前锁的state从0变成1  
                setExclusiveOwnerThread(Thread.currentThread());//如果加锁成功就把当前线程设置成这把锁的独占线程
            else
                acquire(1);  //把当前线程加入到阻塞队列
        } 
}
      

AQS是什么?JUC下同步框架的一个核心的抽象类,可以提供一个很方便的获取或释放资源的同步方式,用一个int属性来判断锁的基本状态,维护了一个先进先出的线程同步队列(加static和final修饰来保证多线程操作的可见),内部属性加了volatile也是来保证多线程操作的可见性,可有序性,在操作volatile修饰的遍历的时候会加内存屏障,同时也保证了有序性。

protected final boolean compareAndSetState(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);//调用native方法把当前的表示从0 变成 1
    }
//如果加锁失败,调用下面方法把线程放到阻塞队列
public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))//这里就做把线程添加到同步等待队列
            selfInterrupt(); //修改当前线程的状态
    }
final boolean acquireQueued(final Node node, int arg) {//添加到队列,大致修改一下队列的相关数据  显示部分
        boolean failed = true;
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();//保存
                if (p == head && tryAcquire(arg)) {
                    setHead(node);//把这个设置成头
                    p.next = null; //清空下一个节点
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
    }
public void unlock() {  sync.release(1);}  //ReentrantLock的开锁操作,调用了下面AQS的代码
​
public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;//这里的head是同步等待队列的面第一个线程
            if (h != null && h.waitStatus != 0)//下一个节点是空,状态不是0
                unparkSuccessor(h);  //开锁
            return true;
        }
        return false;
    }
 //等待队列的头部,上面调用了
 private transient volatile Node head;
 //等待队列的尾部,获取锁失败的时候会添加到这个节点的后面
 private transient volatile Node tail;
 //表示同步状态 获取和释放锁的时候都要用
 private volatile int state;
static final class Node {//部分    主要用来管理同步队列的
    volatile int waitStatus;//等待状态
    volatile Node prev;//上一个节点,就是线程
    volatile Node next;//下一个节点
    volatile Thread thread;//排队的线程
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值