java同步器AQS架构AbstractQueuedSynchronizer原理解析

Java同步器AQS架构AbstractQueuedSynchronizer原理解析

什么是AQS?

抽象队列同步器(AbstractQueuedSynchronizer,AQS)是Java中一种同步工具,它是构建锁与同步器的框架,是并发包中用来构造锁、信号量、倒计数器、线程池等等使用的开发工具类。它采用了一种FIFO的队列等待机制来保证线程执行的顺序。

AQS的核心思想

AQS的核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是通过内部的FIFO队列来实现的。

AQS的核心组成

在AQS中,派生类需要实现以下方法:

  1. isHeldExclusively()
  2. tryAcquire(int)
  3. tryRelease(int)

其中isHeldExclusively()方法判断当前线程是否保持独占模式,只有用到 ReentrantLock 中的 Condition 才需要这个功能。

tryAcquire(int)方法是独占模式下的资源申请。在独占模式下,当拿不到这把锁的时候会将当前线程唤醒,添加到队列中。

tryRelease(int)方法是独占模式下的释放资源。

如何使用AQS

ReentrantLock 为例,演示如何使用AQS。

示例1:简单的 ReentrantLock 使用示例

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockDemo {

    private static Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable() {
                public void run() {
                    lock.lock();
                    try {
                        System.out.println(Thread.currentThread().getName() + "获得了锁");
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        System.out.println(Thread.currentThread().getName() + "释放了锁");
                        lock.unlock();
                    }
                }
            }).start();
        }
    }
}

示例代码中,我们定义了一个 ReentrantLock 对象,然后在一个 for 循环中创建了5个线程,每个线程获取锁、睡眠 500 毫秒进入阻塞状态,然后释放锁。

示例2:Lock 结合 Condition 示例

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockConditionDemo {

    private static Lock lock = new ReentrantLock();
    private static Condition condition = lock.newCondition();

    public static void main(String[] args) {
        new Thread(new Runnable() {
            public void run() {
                try {
                    lock.lock();
                    System.out.println(Thread.currentThread().getName() + "等待信号");
                    condition.await();
                    System.out.println(Thread.currentThread().getName() + "收到信号");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }).start();

        new Thread(new Runnable() {
            public void run() {
                lock.lock();
                System.out.println(Thread.currentThread().getName() + "发出信号通知");
                condition.signalAll();
                lock.unlock();
            }
        }).start();
    }
}

示例代码中,我们定义了一个 ReentrantLock 对象以及一个 Condition 对象,生产者线程发出一个信号通知,然后唤醒等待信号的消费者线程,消费者线程接收到要求后,执行最后的代码逻辑。

总结

通过上面的例子,我们初步了解到了什么是AQS,其核心思想和组成部分,以及如何使用 ReentrantLockCondition 针对 AQS 进行对锁与同步器进行控制的实现方式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java同步器AQS架构AbstractQueuedSynchronizer原理解析 - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • vue 2.0 开发实践总结之疑难篇

    Vue 2.0 开发实践总结之疑难篇的完整攻略 Vue 2.0 是一款流行的前端框架,但在实践中,我们可能会遇到一些疑难问题。本文将为您提供一份详细的 Vue 2.0 开发实践总结之疑难篇的完整攻略,包括两个示例说明。 示例1:如何在 Vue 中使用第三方库? 在 Vue 中使用第三方库可能会遇到一些问题,例如无法正确引入库、无法正确使用库等。可以按照以下步…

    other 2023年5月5日
    00
  • sqlserver中存储过程的递归调用示例

    下面就来详细讲解“sqlserver中存储过程的递归调用示例”的完整攻略吧。 什么是SQL Server中的存储过程? SQL Server中的存储过程是一种预定义的SQL代码块,可以在需要用它的时候重复使用。存储过程可以接受参数,可以返回值,可以处理复杂的查询任务和事务处理等等。其中,递归调用是存储过程的一种特殊形式,它能够在函数内部调用自己,可以用来解决…

    other 2023年6月27日
    00
  • 开发者在Idea 中常见的配置,你都了解吗

    是的,下面是一份“开发者在Idea中常见的配置”的完整攻略。 Idea 概述 Idea是JetBrains公司开发的一个Java 集成开发环境(IDE),支持Java、Kotlin、Python等多种编程语言。是目前主流的Java开发工具之一。在使用Idea进行开发时,有一些常见的配置非常有用。 常见配置 1. JDK 配置 在使用Idea进行Java开发之…

    other 2023年6月26日
    00
  • java联调生成测试数据工具类方式

    以下是使用Java编写测试数据生成工具类的完整攻略: 步骤一:创建测试数据生成工具类 在Java项目中创建一个新的类,命名为TestDataGenerator。 在TestDataGenerator类中添加静态方法,用于生成测试数据。例如: public class TestDataGenerator { public static List<User…

    other 2023年10月16日
    00
  • nodejs使用redis作为缓存介质实现的封装缓存类示例

    接下来我将详细介绍使用Redis作为缓存介质实现封装缓存类的完整攻略,包括安装redis模块、编写缓存类以及使用示例。 安装Redis模块 首先需要在Node.js中安装与Redis交互的模块。可以使用npm命令来安装redis模块,命令如下: npm install redis –save 其中,–save参数表示将该模块添加到package.json…

    other 2023年6月25日
    00
  • JS中封装axios来管控api的2种方式

    在JS中,使用axios作为网络请求库是非常常见的。在实际应用中,我们需要封装axios来管理API,以便于维护和升级。这里介绍两种常见的封装axios的方式。 方式一:基于axios.create()方法 通过axios.create()方法创建一个新的axios实例,然后在这个实例中设置一些统一的请求头、请求拦截器和响应拦截器等。示例代码如下: impo…

    other 2023年6月25日
    00
  • macroot用户初始密码设置

    MacRoot用户初始密码设置 如果您是一位MacRoot用户,那么初次登录时需要设置初始密码,以确保安全性。在这篇文章中,我们将为您提供如何设置自己的MacRoot用户初始密码的详细指南。 步骤1:打开终端 要设置MacRoot用户的密码,首先需要打开您的Mac上的终端。您可以通过按下“ Command + 空格”组合键打开Spotlight搜索,然后输入…

    其他 2023年3月29日
    00
  • Android开发快速实现底部导航栏示例

    Android开发快速实现底部导航栏示例攻略 底部导航栏是Android应用中常见的一种导航方式,它可以让用户快速切换不同的页面或功能。本攻略将详细介绍如何快速实现一个底部导航栏示例。 步骤一:创建项目和布局文件 首先,我们需要创建一个新的Android项目,并在布局文件中定义底部导航栏的外观和位置。 在Android Studio中创建一个新的项目。 打开…

    other 2023年9月6日
    00
合作推广
合作推广
分享本页
返回顶部