面试官:项目中有用过锁吗?能解释一下什么是AQS?

本文介绍了AQS(AbstractQueuedSynchronizer),一种用于构建锁和其他同步组件的基础框架。AQS通过一个int变量表示同步状态,并使用FIFO队列管理线程的同步。子类通过继承AQS并重写相关方法来实现同步控制,如ReentrantLock和ReentrantReadWriteLock。文章还展示了如何自定义一个独占锁,并提供了AQS的关键方法,包括获取和释放同步状态的模版方法。
摘要由CSDN通过智能技术生成

1 前言

锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁能防止多个线程同时访问共享资源(但是有些锁可以允许多个线程并发的访问共享资源,如读写锁)。在以前,Java程序是靠synchronized来实现锁功能的,而在Java SE 5之后,并发包中新增了Lock接口(以及相关实现类)用来实现锁功能,他提供了与synchronized关键字类似的同步功能,只是在使用时需要显式的获取锁和释放锁,虽然它缺少了synchronized提供的隐式获取释放锁的便捷性,但是却拥有了锁获取和释放的可操作性、可中断的获取锁以及超时获取锁等多种synchronized关键字不具备的同步特性。很多锁都通过实现Lock接口来完成对锁的操作,比如可重入锁(ReentrantLock)、前一张讲的Redisson分布式锁等,而Lock接口的实现,基本是都是通过聚合了一个同步器的子类来完成线程访问控制的,而同步器,就是我们常说的AQS(
AbstractQueuedSynchronizer),也是今天要记录的内容。

2 什么是AQS

AQS(队列同步器
AbstractQueuedSynchronizer)是用来构建锁或者其他同步组件的基础框架,它使用了一个int成员变量来表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作。

面试官虚晃一枪:项目中有用过锁吗?能解释一下什么是AQS?

如上图所示,同步器的主要使用方式是继承,子类通过继承同步器并实现它的抽象方法来管理同步状态,在抽象方法的实现过程中免不了要对同步状态进行修改,这时就需要使用同步器提供的3个方法来进行操作:

1、getState():获取当前同步状态

面试官虚晃一枪:项目中有用过锁吗?能解释一下什么是AQS?

2、setState():设置当前同步状态

面试官虚晃一枪:项目中有用过锁吗?能解释一下什么是AQS?

3、compareAndSetState(int expect, int update):通过CAS设置当前状态,该方法能保证状态设置的原子性

面试官虚晃一枪:项目中有用过锁吗?能解释一下什么是AQS?

子类推荐被定义为自定义同步组件的静态内部类,同步器自身没有实现任何同步接口,它仅仅是定义了若干同步状态获取和释放的方法来供自定义同步组件使用。同步器既可以支持独占式获取同步状态(单个线程获取锁),也可以支持共享式获取同步状态(多个线程获取到锁),这样就可以方便实现不同类型的同步组件(如上图所示的可重入锁:ReentrantLock、可重入读写锁:ReentrantReadWriteLock、计数器:CountDownLatch等等)

3 同步器可重写的方法

以下代码为可重入锁继承同步器后重写的方法:

  • protected boolean tryAcquire(int acquires):独占式获取同步锁状态,实现该方法需要查询当前状态并判断同步状态是否符合预期,然后再进行CAS设置同步状态。
    /**
     * 非公平锁
     */
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * Performs lock.  Try immediate barge, backing up to normal
         * acquire on failure.
         */
        final void lock() {
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            // nonfairTryAcquire方法和下面的公平锁方法除了判断是否在队列首位之外没有不同
            return nonfairTryAcquire(acquires);
        }
    }

    /**
     * 公平锁
     */
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            acquire(1);
        }

        /**
         * Fair version of tryAcquire.  Don't grant access unless
         * recursive call or no waiters or is first.
         */
        protected final b
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值