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日

相关文章

  • 有效阻止Win10悄悄下载和更新后自动重启计算机的技巧

    针对“有效阻止Win10悄悄下载和更新后自动重启计算机”的技巧,这里提供一份完整攻略。 有效阻止Win10悄悄下载和更新后自动重启计算机 背景 Win10自从推出以来,强制更新和自动重启问题一直备受诟病。在未经用户同意的情况下,Win10会悄悄地下载更新并自动重启计算机,这不仅浪费了用户的时间,还可能导致一些重要数据的丢失。因此,寻找有效的方法来阻止Win1…

    other 2023年6月27日
    00
  • java通过AOP实现全局日志打印详解

    Java通过AOP实现全局日志打印详解 1. 简介 AOP(面向切面编程)是一种编程范式,可以通过在运行时动态地将代码片段(称为“切面”)插入到程序的特定位置,从而实现一些横切关注点的统一处理。全局日志打印是一个常见的横切关注点,可以通过AOP来实现。 2. 准备工作 在使用AOP实现全局日志打印之前,需要先引入相关的依赖库。这里以使用Spring框架为例,…

    other 2023年6月28日
    00
  • 【vue】vue中遍历数组和对象

    【vue】vue中遍历数组和对象 在vue的开发中,我们经常需要对数组和对象进行遍历,以便在页面中展示数据。本文将介绍vue中遍历数组和对象的两种方式:通过v-for指令遍历和通过js的Object.keys()方法遍历。 遍历数组–v-for指令 在vue中,我们可以通过v-for指令来遍历数组。可以使用v-for指令在template标签中对数组进行遍…

    其他 2023年3月28日
    00
  • 从零开始封装自己的自定义Vue组件

    下面是详细讲解“从零开始封装自己的自定义Vue组件”的完整攻略: 1. 确定组件需求及功能 在封装自定义Vue组件之前,需要先确定需要开发哪些组件,以及组件需要实现哪些功能。对于网站中需要复用的UI元素,可以考虑封装成组件,例如轮播图、瀑布流布局等。 在确定组件需求及功能后,需要根据组件类型及功能,采用不同的基础组件。例如,若需要实现一个表单组件,可以基于I…

    other 2023年6月25日
    00
  • 基于JPA查询部分字段的相关事项

    基于JPA查询部分字段的相关事项需要注意以下几点: 1. 创建DTO对象 在JPA中,为了查询部分字段,需要创建一个DTO(Data Transfer Object)对象来存储查询出的结果。DTO对象一般包含了需要查询的字段,其中字段的类型和名称需要与实体类中对应的字段一致,以便查询结果正确存储。 下面是一个示例,创建一个名为UserDTO的DTO对象,其中…

    other 2023年6月26日
    00
  • Redis中常见的几种集群部署方案

    下面就让我来为你详细介绍一下 Redis 中常见的几种集群部署方案及示例说明: Redis 集群部署方案 Redis 是一种高性能的键值缓存数据库,它在内存中存储数据,提供快速读写操作,并支持持久化功能。由于 Redis 在缓存方面的出色表现,它被广泛用于网站、移动应用等场景中。对于高并发的应用场景,采用 Redis 集群来扩容是必不可少的方法之一。 下面是…

    other 2023年6月27日
    00
  • java EasyExcel实现动态列解析和存表

    Java EasyExcel实现动态列解析和存表 在Java中,EasyExcel是一款非常好用的Excel操作工具。本文将介绍如何使用EasyExcel实现动态列解析和存表。 准备工作 使用EasyExcel需要添加相应的依赖: <dependency> <groupId>com.alibaba</groupId> &l…

    other 2023年6月25日
    00
  • 什么是validationquery

    当然,我很乐意为您提供有关validationQuery的完整攻略。以下是详细的步骤和两个示例: 1. 什么是validationQuery? validationQuery是一个JDBC连接池的配置选项,用于测试连接是否有效。当连接池从数据库获取连接时,它会执行validationQuery语句,如果语句执行成功,则连接有效,否则连接无效。 2. vali…

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