ReentrantLock

AQS(AbstractQueuedSynchronizer)是Java并发包中的基础组件,用于构建锁和同步器。它包含一个双向队列,用于管理等待锁的线程。ReentrantLock利用AQS实现公平锁和非公平锁,通过CAS操作改变state来获取和释放锁。当尝试获取锁失败时,线程会被添加到队列中等待。

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

一、AQS
1、本质

        AQS本质上就是Java中的AbstractQueuedSynchronizer(抽象队列同步器)类,在AbstractQueuedSynchronizer类中,有几个属性和一个双向队列;

        AQS就是并发包下的一个基类,它的实现包括

        CountDownLatch,ReentrantLock,Semaphore....

2、双向队列部分源码(AbstractQueuedSynchronizer类中的内部类)
static final class Node {
        static final Node SHARED = new Node();
        // 排他锁标识
        static final Node EXCLUSIVE = null;

        // 如果带有这个标识,证明是失效了
        static final int CANCELLED =  1;

        // 具有这个标识说明后继节点需要被唤醒
        static final int SIGNAL = -1;

        // Node对象存储标识的地方
        volatile int waitStatus;

        // 指向上个节点,可以看做一个指针
        volatile Node prev;

        // 指向下个节点,可以看做一个指针
        volatile Node next;

        // 当前Node绑定的线程
        volatile Thread thread;

        // 返回前一个节点,前驱节点,如果为null就抛出异常
        final Node predecessor() throws NullPointerException {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }

    }
二、加锁

ReentrantLock可以实现公平锁,也可以实现非公平锁,也是互斥锁和可重入锁(可重入锁原理

1、从lock进入(ReentrantLock类)
    public void lock() {
        // sync分为公平和非公平
        sync.lock();
    }
2、从非公平锁进去(Sync类)
        final void lock() {
            // 通过CAS(轻量级锁的实现方式)的方式将state从0修改为1,如果返回true,代表修改成功
            if (compareAndSetState(0, 1))
                // 将一个属性设置为当前线程,这个属性是AQS的父类提供的
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }
3、查看acquire方法(AQS类)
    public final void acquire(int arg) {
        // tryAcquire()再次尝试获取锁资源,如果尝试成功就直接放回true
        // acquireQueued() 获取锁资源失败后,需要将当前线程封装成一个Node,追加到AQS的队列中
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            // 线程终端
            selfInterrupt();
    }
4、查看tryAcquire方法(AQS类)
	final boolean nonfairTryAcquire(int acquires) {
        // 获取当前线程
		final Thread current = Thread.currentThread();
        // 获取AQS的state的值
		int c = getState();
        // 如果state为0代表尝试再次获取锁资源
		if (c == 0) {
			if (compareAndSetState(0, acquires)) {
				setExclusiveOwnerThread(current);
				return true;
			}
		}
        // 判断当前占有锁资源的线程是否是当前线程
		else if (current == getExclusiveOwnerThread()) {
            // 将state值+1
			int nextc = c + acquires;
			if (nextc < 0) // overflow
                // 超出锁可重入的最大值,抛出Error,增强代码健壮性
				throw new Error("Maximum lock count exceeded");
            // 没有问题就重新对state进行赋值
			setState(nextc);
            // 锁重入成功
			return true;
		}
        // 锁重入失败
		return false;
	}

5、查看addWaiter方法(AQS类)

    // 执行该方法说明前面获取锁资源失败,放到队列中等待
    private Node addWaiter(Node mode) {
        // 创建Node,并且设置thread为当前线程,设置为排他锁
        Node node = new Node(Thread.currentThread(), mode);
        // 获取AQS队列的尾部节点
        Node pred = tail;
        // 如果pred是null,表示队列是空队列,否则表示队列有人排队
        if (pred != null) {
            // 将当前节点的prev,设置为刚才的尾部节点,即把当前节点设置为新的尾节点
            node.prev = pred;
            // 基于CAS方式,将tail节点设置为当前节点
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node);
        return node;
    }

三、释放锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值