AQS的理解

#AQS是什么

AQS(AbstractQueuedSynchronizer)是Java中的一个非常重要的并发编程框架,它提供了一个基于FIFO队列的阻塞锁和相关的同步器(例如信号量、事件等)的框架。
AQS是JUC(java.util.concurrent)包下的一个抽象类,它内部通过一个int类型的成员变量state来表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作。AQS定义了一套多线程访问共享资源的同步器框架,许多同步类实现都依赖于它,如常用的ReentrantLock、CountDownLatch、Semaphore、CyclicBarrier等。

以下是AQS框架的几个核心概念:
同步状态(State):AQS使用一个int类型的变量来表示同步状态,这个状态的具体含义由子类来定义,例如在ReentrantLock中,它表示锁被获取的次数。
FIFO队列:当多个线程尝试获取资源而无法立即获得时,AQS会使用一个内部队列(通常称为CLH队列)来将这些线程排队。队列中的每个节点代表一个等待锁的线程。
独占模式和共享模式:AQS支持两种同步模式,独占模式和共享模式。独占模式表示一次只能有一个线程获取到同步状态,如ReentrantLock。共享模式则允许多个线程同时获取到同步状态,如Semaphore和CountDownLatch。
条件队列:AQS还支持条件队列,允许线程在某个条件下等待或被唤醒,类似于Object的wait()和notify()方法。

在AQS(AbstractQueuedSynchronizer)中,线程更新同步状态(State)是为了实现各种同步器的基本功能

表示锁的状态:在独占锁(如ReentrantLock)的实现中,同步状态通常表示锁的持有情况。例如,状态为0可能表示锁当前是可用的,而状态为1或更大值可能表示锁已被占用,并且如果锁是可重入的,状态值可能会表示锁被同一个线程获取的次数。
资源可用性:在信号量(如Semaphore)中,同步状态表示可用的许可数量。当线程尝试获取许可时,它需要更新状态以减少可用的许可数;当线程释放许可时,它需要更新状态以增加可用的许可数。

CAS

在AQS(AbstractQueuedSynchronizer)中,CAS(Compare And Swap)操作是一种重要的原子性操作,用于实现无锁编程中的线程安全。CAS操作涉及到三个操作数:内存位置(V),预期值(A)和新值(B)。其基本思想是:仅当内存位置的值与预期值相同时,才将内存位置的值修改为新值。这个操作是原子的,意味着它在执行过程中不会被其他线程中断。
在AQS(AbstractQueuedSynchronizer)的独占模式中,多个线程通过CAS(Compare And Swap)操作尝试更新同步状态(State),只有一个线程能够成功更新状态,这通常意味着该线程成功获取到了锁。

以下是CAS操作的基本步骤:

读取:从指定的内存位置读取值。
比较:将读取的值与预期值进行比较。
写入(如果需要):如果读取的值与预期值相等,则将新值写入该内存位置;如果不相等,则不进行任何操

以下是AQS的基本使用方法:

自定义同步器:继承AbstractQueuedSynchronizer类,并覆写指定的方法(例如tryAcquire、tryRelease、tryAcquireShared、tryReleaseShared等)来实现自己的同步语义。
实现同步方法:在自定义同步器中,根据需要实现获取和释放资源的方法,这些方法通常会调用AQS提供的acquire、release、acquireShared、releaseShared等模板方法。
以下是一个简单的自定义同步器示例:

import java.util.concurrent.locks.AbstractQueuedSynchronizer;

public class Mutex implements java.util.concurrent.Lock {
    private static class Sync extends AbstractQueuedSynchronizer {
        // 尝试获取锁
        @Override
        protected boolean tryAcquire(int arg) {
            return compareAndSetState(0, 1);
        }

        // 尝试释放锁
        @Override
        protected boolean tryRelease(int arg) {
            setState(0);
            return true;
        }

        // 是否处于占用状态
        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }
    }

    private final Sync sync = new Sync();

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

    @Override
    public void unlock() {
        sync.release(1);
    }

    // ... 实现其他Lock接口方法
}

在这个示例中,我们定义了一个简单的互斥锁Mutex,它通过内部类Sync继承了AQS,并覆写了tryAcquire和tryRelease方法来定义获取和释放锁的逻辑。通过这种方式,我们可以利用AQS提供的强大功能来实现各种同步需求。

你可能感兴趣的:(springboot,java,开发语言)