当前位置: 代码网 > it编程>编程语言>Java > java之AQS(AbstractQueuedSynchronizer)用法解读

java之AQS(AbstractQueuedSynchronizer)用法解读

2026年01月04日 Java 我要评论
aqs(abstractqueuedsynchronizer)是java并发包(java.util.concurrent)中的一个核心组件,是构建锁和其他同步器的基础框架。以下是对aqs的详细理解:一

aqs(abstractqueuedsynchronizer)是java并发包(java.util.concurrent)中的一个核心组件,是构建锁和其他同步器的基础框架。

以下是对aqs的详细理解:

一、aqs的基本概念

aqs,全称为abstractqueuedsynchronizer,是一个抽象的队列式同步器。

它定义了一套多线程访问共享资源的同步器框架,为java并发同步组件提供统一的底层支持。

aqs是一个为各个同步组件提供基本框架的抽象类,其内部实现了同步状态的管理和线程的排队机制。

二、aqs的核心组件

  1. 同步状态:aqs使用一个int类型的成员变量来表示同步状态。这个状态变量是线程共享的资源,通过内置的fifo队列(先进先出队列)来完成获取资源线程的排队工作。
  2. fifo队列:aqs的底层实现是一个双向链表,用于管理等待获取同步状态的线程。当线程无法获取同步状态时,会被加入到这个队列中等待。
  3. clh队列锁:aqs使用clh队列锁来实现线程的阻塞等待和唤醒机制。clh是一个虚拟的双向队列,即不存在队列实例,仅存在节点之间的关联关系。

三、aqs的工作原理

  1. 获取同步状态:当线程尝试获取同步状态时,会调用aqs的tryacquire方法(对于独占模式)或tryacquireshared方法(对于共享模式)。如果成功获取到同步状态,则返回true;否则,线程会被加入到等待队列中。
  2. 释放同步状态:当线程释放同步状态时,会调用aqs的tryrelease方法(对于独占模式)或tryreleaseshared方法(对于共享模式)。这些方法会修改同步状态的值,并可能唤醒等待队列中的线程。
  3. 线程排队与唤醒:等待获取同步状态的线程会被加入到fifo队列中,并按照队列的顺序等待。当某个线程释放同步状态时,会唤醒队列中的下一个线程来尝试获取同步状态。

四、aqs的资源共享方式

aqs支持两种资源共享方式:独占(exclusive)和共享(share)。

  1. 独占:只有一个线程能执行,如reentrantlock。独占锁又可分为公平锁和非公平锁。公平锁按照线程在队列中的排队顺序来获取锁,非公平锁则允许线程无视队列顺序直接去抢锁。
  2. 共享:多个线程可同时执行,如semaphore、countdownlatch、cyclicbarrier等。共享锁允许多个线程同时访问共享资源。

五、aqs的应用场景

aqs广泛应用于java并发编程中,是实现各种同步机制的基础。

例如,reentrantlock、semaphore、countdownlatch等同步器都是基于aqs实现的。

通过扩展aqs,开发者可以实现各种复杂的同步器,以满足不同的并发编程需求。

六、aqs的优缺点

优点

  1. 提供了统一的同步器框架,简化了同步器的实现过程。
  2. 使用了fifo队列来管理等待线程,保证了线程的公平性。
  3. 提供了灵活的资源共享方式,支持独占和共享两种模式。

缺点

  1. aqs是一个相对复杂的框架,需要开发者对其内部机制有一定的了解才能正确使用。
  2. 在某些情况下,aqs的性能可能不如一些定制的同步器。

七、aqs示例

import java.util.concurrent.locks.abstractqueuedsynchronizer;
import java.util.concurrent.locks.lock;
import java.util.concurrent.timeunit;
import java.util.concurrent.locks.condition;
import java.util.concurrent.locks.locksupport;

// 自定义锁类
class mylock implements lock {
    // 静态内部类,继承aqs
    private static class sync extends abstractqueuedsynchronizer {
        // 是否处于独占模式
        protected boolean isheldexclusively() {
            return getstate() == 1;
        }

        // 尝试获取锁,当状态为0时获取锁成功
        public boolean tryacquire(int acquires) {
            assert acquires == 1; // 只允许获取1个单位的锁
            if (compareandsetstate(0, 1)) {
                setexclusiveownerthread(thread.currentthread());
                return true;
            }
            return false;
        }

        // 尝试释放锁,将状态设置为0
        protected boolean tryrelease(int releases) {
            assert releases == 1; // 只允许释放1个单位的锁
            if (getstate() == 0) throw new illegalmonitorstateexception();
            setexclusiveownerthread(null);
            setstate(0);
            return true;
        }

        // 提供条件变量
        condition newcondition() { return new conditionobject(); }
    }

    // 将操作代理到sync上
    private final sync sync = new sync();

    // 实现lock接口的方法
    @override
    public void lock() {
        sync.acquire(1);
    }

    @override
    public void lockinterruptibly() throws interruptedexception {
        sync.acquireinterruptibly(1);
    }

    @override
    public boolean trylock() {
        return sync.tryacquire(1);
    }

    @override
    public boolean trylock(long time, timeunit unit) throws interruptedexception {
        return sync.tryacquirenanos(unit.tonanos(time));
    }

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

    @override
    public condition newcondition() {
        return sync.newcondition();
    }

    public static void main(string[] args) {
        mylock lock = new mylock();

        runnable task = () -> {
            lock.lock();
            try {
                system.out.println(thread.currentthread().getname() + " 获取锁");
                // 模拟任务执行
                locksupport.parknanos(timeunit.seconds.tonanos(1));
            } finally {
                system.out.println(thread.currentthread().getname() + " 释放锁");
                lock.unlock();
            }
        };

        thread t1 = new thread(task, "thread-1");
        thread t2 = new thread(task, "thread-2");

        t1.start();
        t2.start();
    }
}

mylock类

  • 实现lock接口,内部包含一个静态内部类sync,该内部类继承自abstractqueuedsynchronizer

sync类

  • isheldexclusively:判断当前线程是否持有锁。
  • tryacquire:尝试获取锁,如果当前状态为0(表示锁未被持有),则通过compareandsetstate方法将状态设置为1,并设置当前线程为独占线程。
  • tryrelease:尝试释放锁,将状态设置为0,并清除独占线程。
  • newcondition:创建一个条件变量。

mylock方法

  • lock接口的方法代理到sync对象上。

main方法

  • 创建两个线程,每个线程尝试获取和释放锁,模拟任务执行。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com