前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >AQS队列同步器

AQS队列同步器

作者头像
doper
发布2022-09-26 17:49:49
1870
发布2022-09-26 17:49:49
举报
文章被收录于专栏:后台技术杂项笔记

AbstractQueuedSynchronizer(AQS)队列同步器

1. 什么是AQS

​ AQS主要用来构建或者其他同步器组件的基础框架,它使用了一个int成员变量表示同步状态,通过内置的FIFO队列来完成想获取资源的线程的排队工作。其主要使用方式是继承,子类通过继承它并实现它的抽象方法来管理同步状态,在管理同步状态的时候就需要对同步状态变量(int成员变量)进行修改,为了安全的修改同步状态变量就可以使用AQS已经提供的三个方法(getState()setState(int newState)compareAndSetState(int expect, int update))修改。AQS的子类被推荐定义为自定义同步组件的静态内部类,同步器自身没有实现任何同步接口,可以支持共享式地获取同步状态,可以方便实现不同的同步组件(ReentrantLock,ReentrantReadWriteLock和CountDownLatch等)。

​ 自定义的同步组件(如锁)是面向使用者的,使用者无需关心内部实现,而AQS面向同步组件的实现者的,简化组件的实现方式。

2. AQS接口

  1. AQS同步状态state state为0代表没有线程占有锁,可以去抢这个锁,用CAS设置state为非0,如果CAS成功说明抢到锁了,如果是可重入的话则state可以加1。 state非0代表有线程占有锁,解锁减去1直到state等于0代表释放锁。
  2. AQS的修改同步状态变量的三个方法
    • getState(): 获取当前的同步状态
    • setState(): 设置当前的同步状态
    • compareAndSetState(int expect, int update): 使用CAS设置当前状态,该方法能够保证状态设置的原子性。
  3. AQS可重写的方法 | 方法名称 | 描述 | | ———————————————————————- | —————————————————————————————— | | protected boolean tryAcquire(int arg) | 尝试以独占的方式获取同步状态,这个方法应该查询当前状态是否允许以独占模式获取它,如果允许则可以使用CAS设置同步状态。执行acquire方法的线程会调用此方法,如果此方法失败,则acquire方法可能会将线程排队(如果尚未排队),直到其他线程发出释放信号。这可以用来实现方法Lock.tryLock() | | protected boolean tryRelease(int arg) | 通过尝试修改同步状态变量以释放同步状态,执行release方法的线程会调用这个方法,等待获取同步状态的线程有机会获取同步状态。 | | protected int tryAcquireShared(int arg) | 以共享的方式获取同步状态,此方法应该查询当前状态是否允许以共享模式去获取它,返回大于等于0的值,表示获取成功,反之,获取失败。 | | protected boolean tryReleaseShared(int arg) | 以共享的方式释放同步状态 | | protected boolean isHeldExclusively() | 当前同步器是否在独占模式下被当前线程占用,即表示是否被当前线程所独占。 | 上面方法不重写的话默认实现是抛出UnsupportedOperationException异常
  4. AQS使用例子 在源码中附带了使用例子,具体代码如下:
代码语言:javascript
复制
class Mutex implements Lock, java.io.Serializable {

    // 静态内部类
    // Our internal helper class
    private static class Sync extends AbstractQueuedSynchronizer {
        // Reports whether in locked state
        // 判断是否处于占用状态
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }

        // Acquires the lock if state is zero
        public boolean tryAcquire(int acquires) {
            assert acquires == 1; // Otherwise unused
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());	//AQS中已定义的方法,设置当前拥有独占访问权限的是哪个线程
                return true;
            }
            return false;
        }

        // Releases the lock by setting state to zero
        protected boolean tryRelease(int releases) {
            assert releases == 1; // Otherwise unused
            if (getState() == 0) throw new IllegalMonitorStateException();
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        // Provides a Condition
        Condition newCondition() {
            return new ConditionObject();
        }

        // Deserializes properly
        private void readObject(ObjectInputStream s)
                throws IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // reset to unlocked state
        }
    }

    // 使用Sync完成相关的同步操作
    // The sync object does all the hard work. We just forward to it.
    private final Sync sync = new Sync();

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

    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

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

    public Condition newCondition() {
        return sync.newCondition();
    }

    public boolean isLocked() {
        return sync.isHeldExclusively();
    }

    public boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();
    }

    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    public boolean tryLock(long timeout, TimeUnit unit)
            throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • AbstractQueuedSynchronizer(AQS)队列同步器
  • 1. 什么是AQS
  • 2. AQS接口
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档