AQS锁原理



一、AQS是什么?

AQS(Abstract Queued Synchronizer)是一个抽象的队列同步器,通过维护一个共享资源状态(Volatile Int State)和一个先进先出(FIFO)的线程等待队列来实现一个多线程访问共享资源的同步框架。

二、AQS原理

AQS为每个共享资源都设置一个共享资源锁,线程在需要访问共享资源时首先需要获取共享资源锁,如果获取到了共享资源锁,便可以在当前线程中使用该共享资源,如果获取不到,则将该线程放入线程等待队列(双向队列),等待下一次资源调度,具体的流程如图所示。许多同步类的实现都依赖于AQS,例如常用的ReentrantLockSemaphoreCountDownLatch
在这里插入图片描述

三、STATE:状态

Abstract Queued Synchronizer维护了一个volatile int类型的变量state,用于表示当前的同步状态。Volatile虽然不能保证操作的原子性,但是能保证当前变量state的可见性。

state的访问方式有三种:getState(),setState()、compareAndSetState()均是原子操作,其中,compareAndSetState的实现依赖于Unsafe的compareAndSwapInt()。具体的JDK代码实现如下:

	/**
    * 锁的状态
    */
    private volatile int state;

	//返回共享资源状态,此操作的内存语义为volatile修饰的原子读操作
	protected final int getState() {
        return state;
    }
    
	//设置共享资源状态,此操作的内存语义为volatile修饰的原子写操作
	protected final void setState(int newState) {
        state = newState;
    }
    /*
    *如果当前状态值等于预期值,则原子化地将同步状态设置为给定的更新值。
    *此操作的内存语义为volatile修饰的原子读写操作
    */
    protected final boolean compareAndSetState(int expect, int update) {
        // See below for intrinsics setup to support this
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }

四、AQS共享资源的方式:独占式和共享式

AQS定义了两种资源共享方式:独占式(Exclusive)和共享式(Share)。

  • 独占式(Exclusive):只有一个线程能执行,具体的Java实现有ReentrantLock。
  • 共享式:多个线程可同时执行,具体的Java实现有Semaphore和CountDownLatch。

AQS只是一个框架,只定义了一个接口,具体资源的获取、释放都交由自定义同步器去实现。不同的自定义同步器争用共享资源的方式也不同,自定义同步器在实现时只需实现共享资源state的获取与释放方式即可,至于具体线程等待队列的维护,如获取资源失败入队、唤醒出队等,AQS已经在顶层实现好,不需要具体的同步器再做处理。.

4.1 独占式实现

ReentrantLock对AQS的独占方式实现为:ReentrantLock中的state初始值为0时表示无锁状态。在线程执行tryAcquire()获取该锁后ReentrantLock中的state+1,这时该线程独占ReentrantLock锁,其他线程在通过tryAcquire()获取锁时均会失败,直到该线程释放锁后state再次为0,其他线程才有机会获取该锁。该线程在释放锁之前可以重复获取此锁,每获取一次便会执行一次state+1,因此ReentrantLock也属于可重入锁。但获取多少次锁就要释放多少次锁这样才能保证state最终为0。如果获取锁的次数多于释放锁的次数,则会出现该线程一直持有该锁的情况;如果获取锁的次数少于释放锁的次数,则运行中的程序会报锁异常。

4.1 共享式

CountDownLatch对AQS的共享方式实现为:CountDownLatch将任务分为N个子线程去执行,将state也初始化为N, N与线程的个数一致,N个子线程是并行执行的,每个子线程都在执行完成后countDown()一次,state会执行CAS操作并减1。在所有子线程都执行完成(state=0)时会unpark()主线程,然后主线程会从await()返回,继续执行后续的动作。


总结

AQS是juc包下lock接口的底层实现原理,其维护了一个维护了一个volatile int类型的变量state用来表示锁的状态,并且底层维护了一个双向队列用来阻塞竞争锁的线程,提供了独占式和共享式的资源获取方式,有公平与非公平锁的实现原理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值