3.Java面试题之AQS

news2025/1/24 22:52:58

1. 写在前面

在这里插入图片描述

AQS(AbstractQueuedSynchronizer)是Java并发包(java.util.concurrent)中的一个抽象类,用于实现同步器(如锁、信号量、栅栏等)。AQS提供了一种基于FIFO队列的机制来管理线程的竞争和等待状态。其主要作用是简化同步器的实现,通过提供通用的同步状态管理和线程排队机制,使得开发者可以专注于特定同步器的逻辑。了解AQS的工作原理和应用场景是高级Java开发者需要掌握的重要技能。以下是一些常见的AQS面试题及其详细解答。

2. AQS的工作原理是什么?

AQS的核心工作原理基于一个FIFO等待队列和一个同步状态(state)。其主要步骤如下:

  • 同步状态:AQS通过一个 int 类型的变量 state 来表示同步状态。子类通过重写 tryAcquire、tryRelease 等方法来定义获取和释放同步状态的逻辑。
  • 等待队列:当线程无法获取同步状态时,会被加入到AQS的FIFO等待队列中,队列中的每个节点(Node)表示一个等待的线程。
  • 独占模式和共享模式:AQS支持独占模式(如独占锁)和共享模式(如共享锁、信号量)。在独占模式下,只有一个线程可以获取同步状态;在共享模式下,多个线程可以同时获取同步状态。
  • 模板方法:AQS通过模板方法模式提供了通用的同步机制,子类只需实现特定的同步逻辑。

3. AQS中的Node节点是什么?其作用是什么?

AQS中的Node节点是一个内部类 AbstractQueuedSynchronizer.Node,用于表示等待队列中的每个线程。Node节点包含以下重要信息:

  • 线程引用:表示当前节点所关联的线程。
  • 等待状态:表示当前节点的等待状态,如 SIGNAL(等待唤醒)、CANCELLED(取消)等。
  • 前驱和后继节点:用于在等待队列中形成双向链表。
  • 模式:表示当前节点是独占模式还是共享模式。

Node节点的作用是管理等待队列中的线程状态和排队顺序,确保线程能够按照FIFO顺序被唤醒和执行。

4. AQS中的独占模式和共享模式有什么区别?

AQS支持两种模式:独占模式和共享模式。

4.1 独占模式

  • 只有一个线程可以获取同步状态
  • 典型应用:独占锁(如 ReentrantLock)
  • 主要方法:tryAcquire、tryRelease

4.2 共享模式

  • 多个线程可以同时获取同步状态
  • 典型应用:共享锁(如 ReadWriteLock 中的读锁)、信号量(如 Semaphore)
  • 主要方法:tryAcquireShared、tryReleaseShared

5. 如何使用AQS实现一个简单的独占锁?

可以通过继承AQS并重写其方法来实现一个简单的独占锁。以下是一个示例:

import java.util.concurrent.locks.AbstractQueuedSynchronizer;

public class SimpleLock {
    private static class Sync extends AbstractQueuedSynchronizer {
        @Override
        protected boolean tryAcquire(int arg) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        @Override
        protected boolean tryRelease(int arg) {
            if (getState() == 0) throw new IllegalMonitorStateException();
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        protected boolean isHeldExclusively() {
            return getState() == 1;
        }
    }

    private final Sync sync = new Sync();

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

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

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

6. 如何使用AQS实现一个简单的共享锁?

可以通过继承AQS并重写其方法来实现一个简单的共享锁。以下是一个示例:

import java.util.concurrent.locks.AbstractQueuedSynchronizer;

public class SimpleSharedLock {
    private static class Sync extends AbstractQueuedSynchronizer {
        @Override
        protected int tryAcquireShared(int arg) {
            for (;;) {
                int current = getState();
                int newCount = current + arg;
                if (compareAndSetState(current, newCount)) {
                    return newCount;
                }
            }
        }

        @Override
        protected boolean tryReleaseShared(int arg) {
            for (;;) {
                int current = getState();
                int newCount = current - arg;
                if (compareAndSetState(current, newCount)) {
                    return newCount == 0;
                }
            }
        }
    }

    private final Sync sync = new Sync();

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

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

7. AQS的公平锁和非公平锁有什么区别?

AQS支持公平锁和非公平锁两种模式:

7.1 公平锁

  • 线程按照FIFO顺序获取锁,先到先得。
  • 公平锁避免了线程饥饿,但可能会导致较高的上下文切换开销。
  • 典型实现:ReentrantLock 的公平模式。

7.2 非公平锁

  • 线程可以插队获取锁,不保证FIFO顺序。
  • 非公平锁可能会导致线程饥饿,但通常性能较高,因为减少了上下文切换。
  • 典型实现:ReentrantLock 的非公平模式(默认)。

8. AQS的Condition机制是如何实现的?

AQS的Condition机制通过内部类 ConditionObject 实现。ConditionObject 提供了 await 和 signal 等方法,用于线程的等待和唤醒。其工作原理如下:

  • 等待队列:每个Condition对象都有一个单独的等待队列,线程调用 await 方法时,会被加入到该等待队列中,并释放当前持有的锁。
  • 唤醒机制:线程调用 signal 方法时,会从等待队列中唤醒一个线程,并将其移到同步队列中,等待获取锁。
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;

public class SimpleLockWithCondition {
    private static class Sync extends AbstractQueuedSynchronizer {
        @Override
        protected boolean tryAcquire(int arg) {
            if (compareAndSetState(0, 1)) {
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        @Override
        protected boolean tryRelease(int arg) {
            if (getState() == 0) throw new IllegalMonitorStateException();
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        protected boolean isHeldExclusively() {
            return getState() == 1;
        }

        Condition newCondition() {
            return new ConditionObject();
        }
    }

    private final Sync sync = new Sync();

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1969870.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

condapytorch环境搭建笔记

1. 安装conda 官网安装地址:https://docs.anaconda.com/anaconda/install/linux/ 下载Installer curl -O https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Linux-x86_64.sh注:可以到这里查看和选择适合的版本:https://repo.anacon…

实验2-4-6 求交错序列前N项和

//实验2-4-6 求交错序列前N项和//本题要求编写程序&#xff0c;计算交错序列 1-2/33/5-4/75/9-6/11... 的前N项之和。 #include<stdio.h> #include<math.h> int main(){int n;scanf("%d",&n);//输入在一行中给出一个正整数N。double sum0;for(int i1…

SpringCloud Alibaba 微服务(三):OpenFeign

目录 前言 一、什么是OpenFeign&#xff1f; Feign 的实现 Feign 和 OpenFeign 的区别 二、OpenFeign的优点 三、基本用法 新建子工程 配置文件 服务注册 ​编辑 新建Controller 引入依赖 创建接口 启动类开启Feign注解 访问测试 四、FeignClient 标签的常用属性…

solidity抽象(abstract)合约(很常用)

当合约中至少有一个函数没有被实现&#xff0c; 或者合约没有为其所有的基本合约构造函数提供参数时&#xff0c; 合约必须被标记为 abstract。 即使不是这种情况&#xff0c;合约仍然可以被标记为 abstract&#xff0c; 例如&#xff0c;当您不打算直接创建合约时。 抽象&a…

Langchain-Chatchat3.1——搜索引擎bing与DuckDuckGo

Langchain-Chatchat3.1——搜索引擎bing与DuckDuckGo 1. 前提是咱们的Chatchat服务一起部署好了&#xff0c;可以参考 Langchain-Chatchat3.1版本docker部署流程——知识库问答 2. 搜索引擎 DuckDuckGo&#xff1a;该搜索引擎不需要key&#xff0c;但是需要全球上网服务&…

MongoDB change stream 详解

文章目录 什么是 Chang Streams实现原理故障恢复使用场景Spring Boot整合Chang Stream 什么是 Chang Streams Change Stream指数据的变化事件流&#xff0c;MongoDB从3.6版本开始提供订阅数据变更的功能。 Change Stream 是 MongoDB 用于实现变更追踪的解决方案&#xff0c;类…

MySQL基础练习题16-电影评分

题目 准备数据 分析数据 总结 题目 查找评论电影数量最多的用户名。如果出现平局&#xff0c;返回字典序较小的用户名。 查找在 February 2020 平均评分最高 的电影名称。如果出现平局&#xff0c;返回字典序较小的电影名称。 准备数据 ## 创建库 create database db; u…

微信小程序电商直播功能如何开通?

作者&#xff1a;阿龙 目前&#xff0c;公域直播电商平台&#xff08;抖音、快手、视频号等&#xff09;的获客流量成本越来越高&#xff0c;同时监管规则越来越严&#xff0c;扣点越来越高&#xff0c;并且没有用户分销机制&#xff0c;这些都在迫使商家尽快建立自己的私域直…

苹果Vision Pro在中国市场遇冷?连黄牛都炒不动了

随着科技巨头苹果公司推出的首款混合现实头戴设备Vision Pro正式登陆中国市场&#xff0c;这款备受瞩目的产品引发了广泛关注。 然而&#xff0c;短短一周之后&#xff0c;许多早期尝鲜的用户却开始陆续退场。究竟是什么原因导致大量用户选择退场呢&#xff1f;本文将从多个维…

绝密!OceanBase OBCP备考模拟题讲解(3)

「源de爸讲数据库」每天更新OceanBase OBCP题库及全网独家超详细题目解析&#xff0c;祝您早日持证上岸&#xff01; 现如今&#xff0c;一大批国产数据库随着国产化浪潮&#xff0c;已经逐步被越来越多的人认可。OceanBase便是其中一个优秀代表。 做这个日更专题&#xff0c…

ESP32-C2 烧录

自动下载电路 dtr rts &#xff1b;WCH 提供了相应的芯片&#xff0c;实现自动下载 CH340X &#xff08;*不要使用天问的下载器&#xff0c;电压为5V&#xff0c;下载前会重启电源&#xff0c;导致无法识别ESP芯片&#xff0c;修改&#xff0c;将电源线重引出 使用IDF编辑完成…

实测体验:劣质宠物空气净化器有啥危害?值得买的养宠空气净化器

作为一名猫咖店老板&#xff0c;换季时节&#xff0c;家中不仅要面对恼人的异味&#xff0c;还要忍受满天飞舞的猫毛&#xff0c;真是让人头疼。虽然和毛孩子在一起充满了乐趣&#xff0c;但随之而来的毛发和异味问题却令人苦不堪言。普通的空气净化器虽然能净化空气&#xff0…

写一个图片裁剪的js,JavaScript图片裁剪插件PlusCropper

在前端开发中&#xff0c;图片裁剪是一个常见的需求。本文将深入解析一个功能完善的JavaScript图片裁剪插件——PlusCropper&#xff0c;带你一步步了解其实现原理和使用方法。 一、插件概述 PlusCropper是一个轻量级的JavaScript插件&#xff0c;它允许用户在网页上交互式地…

CTFHUB-文件上传-双写绕过

开启题目 1.php内容&#xff1a; <?php eval($_POST[cmd]);?> 上传一句话木马 1.php&#xff0c;抓包&#xff0c;双写 php 然后放包&#xff0c;上传成功 蚁剑连接 在“/var/www/html/flag_484225427.php”找到了 flag

How Can I display Reference/Citation using Streamlit Application?

题意&#xff1a;怎样在Streamlit应用程序中显示参考文献或引用&#xff1f; 问题背景&#xff1a; I have created an Azure AI Search Service, created index using Azure Blob Storage and Deployed a web application and made a chat Playground using AzureOpenAI. 我…

CSS使用渐变实现Chrome标签栏效果

这次来看一个带特殊圆角导航栏布局&#xff0c;如下谷歌浏览器的标签栏&#xff1a; 这样一个布局如何实现呢&#xff1f; CSS 渐变几乎是无所不能的&#xff0c;什么的图形都能绘制&#xff0c;这里可以拆分一下&#xff0c;两个矩形&#xff0c;两个圆形&#xff0c;还有两个…

计算机毕业设计选题推荐-二手闲置交易系统-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

目标检测 | yolov2/yolo9000 原理和介绍

前言&#xff1a;目标检测 | yolov1 原理和介绍 简介 论文链接&#xff1a;https://arxiv.org/abs/1612.08242 时间&#xff1a;2016年 作者&#xff1a;Joseph Redmon  作者首先在YOLOv1的基础上提出了改进的YOLOv2&#xff0c;然后提出了一种检测与分类联合训练方法&#…

【Linux网络编程】套接字Socket(UDP)

网络编程基础概念&#xff1a; ip地址和端口号 ip地址是网络协议地址&#xff08;4字节32位&#xff0c;形式&#xff1a;xxx.xxx.xxx.xxx xxx在范围[0, 255]内&#xff09;&#xff0c;是IP协议提供的一种统一的地址格式&#xff0c;每台主机的ip地址不同&#xff0c;一个…

五个优秀的免费 Ollama WebUI 客户端推荐

认识 Ollama 本地模型框架&#xff0c;并简单了解它的优势和不足&#xff0c;以及推荐了 5 款开源免费的 Ollama WebUI 客户端&#xff0c;以提高使用体验。 什么是 Ollama&#xff1f; Ollama 是一款强大的本地运行大型语言模型&#xff08;LLM&#xff09;的框架&#xff0c…