ReentrantLock

问题 ReentrantLock 是什么?为什么已经有 synchronized 了还需要它? ReentrantLock 和 synchronized 有什么区别? ReentrantLock 为什么叫“可重入锁”?可重入是怎么实现的? ReentrantLock 底层是怎么实现的? AQS 是什么 state 表示什么 exclusiveOwnerThread 表示什么 一个线程调用 lock() 以后,完整的加锁流程是什么? CAS 抢锁 抢锁失败以后怎么办 什么时候进入等待队列 什么时候阻塞线程 AQS 的等待队列是什么结构? CLH 队列 head tail Node 等待线程是怎么被阻塞和唤醒的? LockSupport.park() LockSupport.unpark() unlock() 的完整流程是什么? state 怎么减少 什么时候真正释放锁 怎么唤醒下一个线程 ReentrantLock 是怎么实现可重入的? 公平锁和非公平锁有什么区别? new ReentrantLock(true) 为什么默认是非公平锁 非公平锁为什么吞吐量通常更高 tryLock() 和 lock() 有什么区别? 立即失败 超时获取 适合什么场景 lockInterruptibly() 是什么?和 lock() 有什么区别? Condition 是什么?为什么有了 wait/notify 还需要 Condition? 一个 ReentrantLock 为什么可以创建多个 Condition? Condition.await() 和 signal() 的底层流程是什么? Condition Queue AQS Queue await 为什么会释放锁 signal 为什么不是直接让线程继续执行 ReentrantLock 使用时为什么必须在 finally 里 unlock()? ReentrantLock 会发生死锁吗?常见死锁场景有哪些? ReentrantLock 和 synchronized 在性能上谁更好? 实际业务中什么时候更适合用 synchronized,什么时候更适合用 ReentrantLock? 如果让你手写一个简化版互斥锁,你会怎么基于 AQS 实现? 为什么已经有 synchronized 了,还需要 ReentrantLock? ReentrantLock 本质上也是一种互斥锁,用来控制多个线程对共享资源的访问。 ...

2026-09-28 · 4 分钟 · Yawen Yang

synchronized

相关问题 synchronized 本质上解决什么问题? synchronized 除了互斥,还提供哪些内存语义? synchronized 修饰实例方法时,锁的是谁? synchronized 修饰静态方法时,锁的是谁? synchronized(obj) 锁的又是谁? 两个不同对象分别调用同一个实例 synchronized 方法,会互相阻塞吗?为什么? static synchronized 方法通过类名调用和通过对象调用,有没有竞争关系?为什么? 一个 static synchronized 方法和一个实例 synchronized 方法之间是否竞争? 为什么 synchronized 是可重入锁? 什么叫“可重入”? 一个同步方法内部再调用另一个锁住同一对象的同步方法,会不会死锁? synchronized 代码块在字节码层面和什么指令有关? synchronized 方法又是如何标识的? synchronized 和对象头、Mark Word、Monitor 有什么关系? 传统意义上的锁升级过程是什么? 为什么现代 JDK 里不能再简单把偏向锁当成重点来讲? synchronized 在竞争激烈时为什么可能进入重量级 Monitor? synchronized 的三种使用方式 synchronized 主要有三种使用方式:修饰实例方法、修饰静态方法、修饰代码块。三者最核心的区别就在于:锁对象不同。 修饰实例方法时: 1 2 public synchronized void method() { } 锁的是当前实例对象,也就是 this。 因此,如果两个线程操作的是同一个实例,它们会互斥;如果操作的是不同实例,因为锁对象不同,通常不会互相阻塞。 修饰静态方法时: 1 2 public static synchronized void method() { } 锁的是当前类对应的 Class 对象,也就是: ...

2026-09-28 · 3 分钟 · Yawen Yang

线程池

相关问题 为什么需要线程池?直接 new Thread() 有什么问题? ThreadPoolExecutor 的核心参数有哪些?这些参数之间是什么关系? 一个任务提交到线程池后,完整执行流程是什么? 什么时候创建核心线程 什么时候进队列 什么时候扩到最大线程数 什么时候触发拒绝策略 为什么达到核心线程数以后,线程池选择先入队,而不是直接扩容线程? 任务队列为什么通常推荐有界队列?无界队列会带来什么问题? OOM 延迟不断增加 maximumPoolSize 很难生效 线程池的几种拒绝策略分别是什么?实际业务应该怎么选? AbortPolicy CallerRunsPolicy DiscardPolicy DiscardOldestPolicy CallerRunsPolicy 为什么能形成反压 CPU 密集型和 IO 密集型任务,线程数应该怎么配置?为什么? IO 密集型线程是不是越多越好?还要受哪些资源限制? 数据库连接池 HTTP 连接池 下游服务容量 CPU 上下文切换 线程池里的空闲线程是怎么回收的? keepAliveTime 核心线程和非核心线程的区别 allowCoreThreadTimeOut 为什么生产环境通常不建议直接使用 Executors.newFixedThreadPool() 和 newCachedThreadPool()? 线程池实现异步和 MQ 实现异步有什么区别?什么时候用线程池,什么时候用消息队列? 如果让你设计一个生产环境线程池,你会重点考虑哪些指标和参数? 核心线程数 最大线程数 队列大小 拒绝策略 任务耗时 CPU 使用率 活跃线程数 队列长度 下游承载能力 结构化八股 为什么需要线程池 如果每个任务都直接 new Thread(),高并发时线程数量会不断增长。线程的创建、销毁、内存占用以及上下文切换都有成本,线程过多反而会降低系统整体效率。 因此线程池首先解决的是线程复用和并发控制:提前维护一批线程,任务来了就交给这些线程执行,任务结束后线程不销毁,而是继续处理后续任务。 固定线程不够怎么办 固定线程数虽然避免了线程无限增长,但如果任务突然增多,线程全部忙起来,剩余任务就需要有地方暂存。 于是线程池引入了 workQueue。当线程暂时处理不过来时,新任务先进入队列,等已有线程执行完当前任务后,再继续从队列中取任务。 队列也不能无限增长 任务队列解决了短时间流量突增的问题,但如果任务进入速度长期大于处理速度,队列就会不断积压。无界队列可能最终占满内存,即使没有 OOM,任务等待时间也会越来越长。 ...

2026-09-28 · 1 分钟 · Yawen Yang