标签题目
多线程相关面试题
分布式系统中的一致性怎么保证?
这题考察一致性目标拆解、复制提交协议、读写路径取舍和故障后的收敛能力,不能只背 CAP 或只说加锁。
数据库事务是什么,ACID 分别代表什么?
这题考察事务边界、ACID 语义、日志恢复、隔离级别和业务不变量,重点是把概念落到数据库执行机制。
ZooKeeper 实现分布式锁的原理是什么?
这题考察临时顺序节点、前驱监听、会话语义和异常重试流程,重点是说明为什么相对公平且能避免惊群。
消费者端幂等性如何实现?
这题考察至少一次投递下的消费安全,核心是用业务唯一键、可靠去重记录和状态机把重复消息变成无副作用。
线程安全的单例模式怎么写?
这题考察 Java 单例在并发下的安全发布、延迟初始化、重排序风险,以及枚举、静态内部类、DCL 各自的边界。
同题还出现在 1 个公司岗位
协程解决什么问题,和线程性能怎么比较?
这题考并发模型和性能边界,回答要说明协程降低的是调度和内存成本,不是让 CPU 计算突破核心数。
CPU load 是什么?
这题考 Linux 性能指标理解,回答要区分 load average、CPU 使用率、核数和不可中断 I/O 等待。
多线程如何防止并发问题?
这题考并发安全的系统化处理,回答要先减少共享,再对必须共享的状态保证原子性、可见性和有序性。
volatile 的原理是什么,能否替代锁?
考察 Java 内存模型,核心是 volatile 保证可见性和有序性,但不保证复合操作原子性,不能替代锁保护临界区。
MySQL 支持哪些隔离级别,对应实现原理是什么?
考察 MySQL InnoDB 隔离级别、MVCC、ReadView、undo log 和锁机制,重点是快照读与当前读的实现差异。
MVCC 的实现原理是什么?
MVCC 是多版本并发控制,通过为数据保留多个历史版本,让读操作基于一致性快照判断可见版本,从而减少读写互相阻塞。常见实现依赖隐藏版本字段、undo log、ReadView 和可见性规则。
Java Object 类有哪些常见方法?
Java Object 类是所有类的根类,常见方法可以分为对象身份相关、运行时类型相关、字符串表示、克隆、线程协作和对象生命周期几类。面试回答要说明方法用途,也要点出 equals/hashCode、wait/notify、clone、finalize 的关键边界。
ReentrantLock 如何基于 AQS 实现可重入锁?
ReentrantLock 的核心不是自己从零管理阻塞队列,而是把获取锁、释放锁、排队、唤醒、可中断等待、条件队列等通用同步能力交给 AQS。它用 AQS 的 state 表示重入次数,用独占线程记录锁持有者,通过公平或非公平策略决定是否允许新线程插队。
AQS 是什么?
AQS 是 Java 并发包中的基础同步框架,用一个 volatile state 表示同步状态,用一个 FIFO 等待队列管理竞争失败的线程,并通过模板方法把通用排队唤醒流程和具体同步语义分离。
Java 线程池有哪些核心参数?
Java 线程池的核心参数来自 ThreadPoolExecutor:corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue、threadFactory、RejectedExecutionHandler。真正要掌握的是它们如何共同决定线程创建、任务排队、扩容、回收和拒绝策略。
synchronized 和 ReentrantLock 有什么区别?
synchronized 是 JVM 层面的内置锁,语法简单,自动加锁释放;ReentrantLock 是 JUC 提供的显式锁,基于 AQS,功能更丰富。两者都可重入,都能保证互斥和可见性,但在使用方式、等待能力、公平性、条件队列和可中断性上差异明显。
MySQL 如何防止幻读?
MySQL 防止幻读要分清快照读和当前读。InnoDB 在可重复读下通过 MVCC 让普通查询看到稳定快照,通过 next-key lock 和 gap lock 保护范围加锁查询,从而阻止其他事务在范围内插入新记录。
客户端 Crash 发生后如何定位问题?
客户端 Crash 定位要从复现、日志、崩溃栈、符号化、版本环境、用户操作路径和近期变更入手,先判断是 Java/Kotlin 异常、Native 崩溃、ANR、OOM 还是系统兼容问题,再结合监控聚合和最小复现找到根因。
Java 有哪些常见加锁机制?
Java 常见加锁机制包括 synchronized、ReentrantLock、ReadWriteLock、StampedLock、原子类和基于 AQS 的同步器。面试重点不是罗列名称,而是说明它们的互斥语义、可重入性、公平性、可中断、条件等待、读写并发和适用场景。
JVM 线程栈大小参数 -Xss 如何设置?
这道题考察的是 JVM 运行时栈内存模型和线程栈参数。核心结论:每个 Java 线程都有独立的 Java 虚拟机栈,方法调用会不断压入栈帧;递归过深或调用链过深通常会触发 StackOverflowError;线程创建过多、每个线程栈过大或系统/容器可用内存不足时,可能触发 OutOfMemoryError: unable to create new native thread。JVM 中常用 -Xss 设置单个线程的栈大小。
StringBuffer的append和String的+=区别?
StringBuffer 的 append 是在同一个可变字符缓冲区上追加内容;String 的 += 表面像修改字符串,实质通常是生成新的字符串结果。核心区别在于 String 不可变,+= 的优化依赖编译器和上下文,循环拼接容易产生大量临时对象;StringBuffer 维护可变缓冲区,append 多次追加时复用内部数组,并通过同步方法提供线程安全,但也带来锁开销。
开放性问题,菜鸟无人仓机器人从A到B,需要多个机器人到达,怎么样效率最高?
这道题考察的是无人仓机器人路径规划与多机器人调度能力,核心不是单个机器人走最短路,而是在有限通道、有限交汇点、有限充电与装卸资源下,让多个仓储机器人安全、有序、稳定地从A到B完成任务。高质量回答应先定义效率目标,再建立仓库图模型,接着讨论多智能体路径规划、冲突避免、任务分配、在线重规划和仿真评估。
进程通信方式分别适合什么场景?
这道题考察的不是背诵 IPC 名词,而是能否根据进程关系、通信方向、数据量、时延、可靠性、同步需求和部署范围选择合适方案。回答时应先按场景分类:父子进程简单字节流用管道,本机无亲缘进程可用 FIFO、消息队列或本地 Socket,高吞吐大块数据用共享内存配合同步原语,事件通知用信号,跨主机通信用网络 Socket,文件或 mmap 适合持久化、低频共享和大文件映射。
StringBuffer的底层数据结构?
StringBuffer 的底层核心是一个可变的连续缓冲区,而不是每次修改都创建新的 String。常见实现中,真正负责存储、长度、容量和扩容的是 AbstractStringBuilder;早期实现可理解为 char[],JDK 9+ 常见实现为了紧凑字符串改为 byte[] 加 coder 标记,但对外仍表现为可变字符序列。StringBuffer 的特点是在这套可变缓冲区能力之上,用 synchronized 保护关键操作,因此适合多个线程共享同一个实例时使用;单线程场景通常优先 StringBuilder。
进程如何保证并发?
进程保证并发,本质上不是某个进程自己保证,而是操作系统通过调度、上下文切换、多核执行、地址空间隔离、进程间通信、同步原语和资源管理共同实现。面试回答要把能同时推进和安全地同时推进区分开:前者靠调度器和 CPU 时间片,后者靠隔离边界、受控共享、锁与信号量、死锁预防以及内核对资源的统一仲裁。
数据库中乐观锁和悲观锁的应用场景是什么?
乐观锁适合读多写少、冲突概率低、业务能接受失败重试的场景;悲观锁适合写冲突高、强一致要求高、不能接受并发覆盖或超卖的场景。回答要围绕版本号/CAS、update where version、重试策略、select for update、行锁、事务边界、死锁风险、隔离级别和幂等性展开。
AQS 的核心原理是什么?
AQS 是 Java 并发包中很多同步器的基础框架,它用一个 volatile 的 state 表示同步状态,用 CAS 保证状态修改的原子性,并通过一个变体 CLH 双向等待队列管理竞争失败的线程。面试回答时要把它讲成“状态管理 + 队列排队 + 阻塞唤醒 + 模板方法扩展”的组合,而不是只背 ReentrantLock 底层用了 AQS。
多线程如何在多个CPU上分布?
多线程并不是由程序自己平均分到多个 CPU 上,而是由操作系统调度器把处于可运行状态的线程调度到逻辑 CPU 上执行。线程能否真正并行,取决于可运行线程数、CPU 核心数或逻辑 CPU 数、调度策略、亲和性、负载均衡、锁竞争、I/O 等待、缓存与 NUMA 局部性等因素。
操作系统: 操作系统都有哪些内容?
这道题看似在问操作系统包含什么,实际考察候选人是否能把零散知识组织成一张系统地图:从进程线程、调度、同步互斥,到虚拟内存、文件系统、I/O、网络、系统调用、安全隔离、死锁和性能诊断。优秀回答不应只罗列名词,而要说明操作系统作为硬件与应用之间的管理层,如何抽象资源、分配资源、保护资源,并在并发、高性能和可靠性之间做权衡。
进程通信的方式有哪些?
进程间通信本质是在独立地址空间之间传递数据、同步状态或通知事件。回答不能只背名称,要按数据通道、同步机制、适用范围和性能代价展开,重点比较管道、命名管道、消息队列、共享内存、信号量、信号、Socket、Unix domain socket、mmap 和文件锁。
过去经历中怎么应对高并发或高性能场景的?
高并发或高性能场景不是考单点技术名词,而是考候选人能否把真实工程问题讲成闭环:先明确业务目标和容量指标,再通过压测和可观测性找到瓶颈,随后从流量、应用、缓存、队列、数据库、线程池、连接池、锁竞争、水平扩展和稳定性预案等层面治理,最后用结果指标证明方案有效。
锁的实现原理是什么?
锁的实现原理可以概括为:用一个可被原子修改的状态表示锁是否被占用,用所有者信息判断谁持有锁,用等待队列管理竞争失败的线程,用阻塞与唤醒降低空转成本,并通过内存屏障建立临界区内外的可见性与有序性保证。理解锁不能只停留在“加锁和解锁”两个动作,而要能讲清互斥、状态变更、线程挂起、唤醒、公平性、重入、超时、中断和竞争优化之间的关系。
可重入锁的原理?
可重入锁的核心原理是:锁不仅记录有没有被占用,还记录被哪个线程占用以及同一线程重复进入了多少次。当持有锁的线程再次请求同一把锁时,不会被自己阻塞,而是把重入计数加一;退出时计数减一,只有计数归零才真正释放锁并唤醒后续等待线程。Java 中 synchronized 和 ReentrantLock 都支持可重入,但实现层次不同:synchronized 由 JVM 管理监视器和锁记录,ReentrantLock 主要基于 AQS 的 state、独占线程 owner、等待队列、CAS 和 park/unpark 实现。
读写锁怎么实现?
读写锁的核心是把访问分成共享读和独占写:多个读线程可以同时进入,写线程进入时必须排斥所有读线程和其他写线程。Java 的 ReentrantReadWriteLock 基于 AQS 实现,用同一个 state 同时记录读锁和写锁计数,并支持可重入、公平策略、锁降级等语义。
Redis 分布式锁如何实现?
Redis 分布式锁的核心不是用一个 key 表示占用,而是要同时解决互斥、死锁、误删、超时、续期、主从切换和业务兜底。标准实现通常是 SET key token NX PX ttl 获取锁,用唯一 token 标识持有者,用 Lua 脚本先比较 token 再删除来释放锁。
线程锁锁的到底是什么?
线程锁并不是把某个线程本身锁住,也不是直接把一段代码或一个变量物理锁住。更准确地说,锁是一种同步协议:它通过某个可竞争的同步状态,约束多个线程进入临界区的顺序,从而保护共享资源及其不变量。Java 中 synchronized 竞争的是对象监视器或类对象监视器,ReentrantLock 竞争的是基于 AQS 维护的同步状态;操作系统层面的 mutex、semaphore 等竞争的是内核或用户态维护的同步状态。
mysql慢查询优化方案?
这道题考察的不是背几个索引原则,而是候选人能否把“发现慢查询、判断瓶颈、制定优化方案、验证效果、防止回退”串成闭环。优秀回答应覆盖慢查询日志与监控定位、EXPLAIN 执行计划分析、索引设计、SQL 改写、表结构与数据规模治理、分页与排序优化、锁等待排查、缓存与业务链路优化,以及上线后的持续观测。
内存资源很宝贵,为什么不能直接访问数据库表?
不能直接访问数据库表的原因是,表不是应用进程里可随意读取的一块内存数组,而是数据库引擎管理的持久化数据结构。应用需要通过 SQL、连接、权限、索引、事务和数据库协议访问数据;数据库内部再决定从磁盘、Buffer Pool、索引页或缓存中读取哪些页。绕过数据库引擎或把全表搬到内存,会破坏一致性、并发控制、恢复能力、安全边界和资源隔离。
InnoDB 和 MyISAM 区别?
InnoDB 和 MyISAM 的核心区别不是简单的谁快谁慢,而是存储引擎目标不同。InnoDB 面向事务一致性、崩溃恢复和高并发 OLTP,支持事务、行级锁、MVCC、外键、聚簇索引和可靠恢复;MyISAM 是早期非事务引擎,主要使用表级锁,不支持事务和外键,恢复能力弱,适合范围非常有限。
MySQL事务的四种特性,分别解释?
MySQL 事务的四种特性是 ACID:原子性、一致性、隔离性、持久性。在 InnoDB 中,原子性主要依赖 undo log 回滚;隔离性依赖 MVCC、ReadView 和锁;持久性主要依赖 redo log 及刷盘机制;一致性不是某一个日志单独保证的,而是由数据库约束、事务语义、隔离控制、崩溃恢复和应用正确性共同保证。
MySQL 事务隔离级别有哪些?
这题考察对 SQL 标准隔离级别和 MySQL InnoDB 实现差异的理解。面试中不能只背四个名字,还要说明每个级别解决哪些并发读问题、MySQL 默认为什么是可重复读,以及 InnoDB 通过 MVCC、快照读、当前读和 next-key lock 在不同读场景下处理一致性与幻读的边界。
了解哪些不同 JDK 版本的新特性?
这道题考察的不是背版本号,而是能否把 JDK 演进和工程实践联系起来。回答时应先按主线概括:JDK 8 是现代 Java 的分水岭,引入 Lambda、Stream、Optional、默认方法和新的日期时间 API;JDK 9 到 10 开始模块化、集合工厂方法、JShell、接口私有方法和局部变量类型推断;JDK 11 作为常用长期支持版本,补齐 HTTP Client、字符串和文件 API、ZGC 初步可用等能力;JDK 17 是当前大量生产系统升级的关键长期支持版本,带来 sealed class、record、switch 表达式、文本块、模式匹配等语言能力,并强化 JVM、GC 和封装边界;JDK 21 进一步把虚拟线程、结构化并发、模式匹配 switch、record pattern、分代 ZGC 等特性推向成熟,重点提升高并发服务的线程模型和表达能力。
synchronized底层实现的原理?
synchronized 是 JVM 级别的内置同步机制。它通过 monitorenter/monitorexit 或方法访问标志进入对象监视器,基于对象头 Mark Word 记录锁状态,并在不同竞争程度下使用轻量级锁、重量级锁等实现互斥。它支持可重入,退出同步块会建立 happens-before 关系,也与 wait/notify 的条件等待机制绑定。
volatile 的作用和底层原理是什么?
volatile 是 Java 并发里用于解决共享变量可见性和一定程度有序性的轻量级机制。它保证对 volatile 变量的写入对后续读取可见,并通过 JMM 规定的 happens-before 关系约束指令重排;但它不保证 i++、check-then-act 这类复合操作的原子性。
Java 线程池的核心参数和执行流程是什么?
这道题考察的不是背出几个构造参数,而是要说明 ThreadPoolExecutor 如何用线程数、队列、线程工厂和拒绝策略共同定义资源边界。高质量回答应先点明线程池复用线程、控制并发、削峰和保护系统的目的,再按任务提交后的执行路径解释:先看核心线程,再入队,再扩容到最大线程,最后触发拒绝策略,同时补充队列选择、参数取舍、异常处理、关闭流程和线上监控。
synchronized锁底层CS了解么?
synchronized 是 JVM 提供的内置互斥机制,核心不是简单的操作系统锁,而是围绕对象头 Mark Word、Monitor 监视器和字节码 monitorenter/monitorexit 协作完成。它支持可重入,具备明确的内存可见性语义,并会结合轻量级锁、CAS、重量级锁以及锁消除、锁粗化等优化来降低同步成本。
java中加锁的方式有哪些,怎么个写法?
Java 加锁常见方式包括 synchronized、ReentrantLock、ReadWriteLock、StampedLock,以及更轻量的原子类、并发容器、线程封闭等替代方案。面试回答不能只背 API,重点要说清楚锁住的对象、写法、释放方式、适用场景、风险和性能取舍。
java中的锁有哪些?
Java 中的锁不能只回答 synchronized 和 ReentrantLock,而要按实现机制、语义特征、等待方式、读写模型和 JVM 优化层级来拆解。面试时应从对象监视器、AQS 显式锁、读写锁、StampedLock、CAS 原子类、LockSupport 与 Condition 这些核心工具出发,再说明乐观/悲观、公平/非公平、可重入/不可重入、自旋/阻塞等分类维度,并结合适用场景、性能取舍和常见陷阱给出判断依据。