多线程问!

2.4 CAS 知道吗?

CAS 就是 Compare And Swap,比较并交换,它体现的是乐观锁思想。

它会比较当前内存值和期望值,如果相等,就更新成新值;如果不相等,说明被其他线程改过,就更新失败,通常会自旋重试。

Java 里的 Atomic 类和 AQS 都大量用了 CAS。它底层依赖 CPU 原子指令保证比较和更新的原子性。CAS 的优点是低竞争下避免加锁阻塞,但缺点是高竞争会自旋浪费 CPU,也有 ABA 问题。

2.5 请谈谈你对 volatile 的理解

volatile 我理解它主要解决两个问题:一个是可见性,一个是禁止指令重排序。

可见性就是说,一个线程修改了 volatile 变量之后,其他线程后续读取这个变量时,能够读到最新值,不会一直读自己线程里的旧缓存。禁止重排序主要是通过内存屏障实现的,保证 volatile 读写前后的指令不会被随意调整,比如双重检查锁里就需要 volatile 防止对象还没初始化完就被其他线程拿到。

但 volatile 有个重要限制,它不保证复合操作的原子性。比如 volatile int count,执行 count++ 还是线程不安全,因为 ++ 包含读取、加一、写回三步,多个线程并发时还是会丢失更新。所以 volatile 更适合做状态标记,或者配合一些特定场景使用,不能替代 synchronized 或 Atomic 类。

2.6 什么是AQS?

AQS 是 AbstractQueuedSynchronizer,可以理解成 JUC 里面很多锁和同步器的基础框架,比如 ReentrantLock、Semaphore、CountDownLatch 底层都跟它有关。

它的核心主要是两部分:一个是 state,一个是 FIFO 等待队列。state 是一个同步状态,具体含义由不同工具自己定义。比如 ReentrantLock (阻塞式锁)里,state 表示锁的重入次数;Semaphore 里表示剩余许可数量;CountDownLatch (倒计时锁)里表示倒计数。修改 state 时通常会用 CAS 来保证线程安全。

大概流程是:线程先尝试获取 state,如果获取成功就继续执行;如果失败,就会被封装成节点放到 AQS 的等待队列里阻塞。等持有资源的线程释放之后,再唤醒队列里的后继线程继续竞争。

所以我理解 AQS 的核心就是:用 state 管资源状态,用 CAS 改状态,用 FIFO 队列管理等待线程。

2.7 ReentrantLock的实现原理

ReentrantLock 是一个可重入互斥锁,使用上是通过 lock() 获取锁,unlock() 释放锁。它底层主要是基于 AQS 实现的。

在 ReentrantLock 里,AQS 的 state 表示锁的重入次数。state=0 表示锁还没人持有,线程加锁时会通过 CAS 尝试把 state 从 0 改成 1,成功就说明拿到了锁,同时会记录当前持锁线程。如果同一个线程再次调用 lock(),不会阻塞,而是直接让 state++,这就是可重入。

如果其他线程来抢锁失败,就会被封装成节点放进 AQS 的 FIFO 等待队列里阻塞。释放锁时,每次 unlock() 会让 state--,只有减到 0 才算真正释放锁,然后会唤醒队列里的后继线程继续竞争。

它还支持公平锁和非公平锁,默认是非公平锁。非公平锁线程来了会先尝试直接抢锁,可能插队;公平锁会先看队列里有没有线程在等,有的话就排队,所以公平锁更公平,但性能通常差一点。

2.8 synchronized和Lock有什么区别 ?

synchronized 和 Lock 都可以实现互斥和可重入,但它们最大的区别是使用方式和功能灵活性不一样。

synchronized 是 Java 关键字,由 JVM 管理锁的获取和释放。进入同步代码块时自动加锁,退出代码块或者发生异常时也会自动释放,所以用起来比较简单,不容易忘记释放锁。

Lock 是 JUC 里的接口,常见实现是 ReentrantLock。它需要手动调用 lock() 和 unlock(),所以一般要把 unlock() 放到 finally 里,避免异常导致锁不释放。它的优势是功能更灵活,比如可以尝试获取锁 tryLock(),可以超时等待,可以响应中断,也可以选择公平锁,还支持多个 Condition 条件队列。

性能上现在不能简单说谁一定更快。synchronized 经过 JVM 优化后性能已经不差。一般简单同步场景我会优先用 synchronized;如果需要可中断、超时、公平锁或者多个条件队列,就用 ReentrantLock 这类 Lock 实现。

相关推荐
软件技术NINI27 分钟前
基于SpringBoot和Vue的新能源汽车销售推荐系统
java·vue.js·spring boot·后端·汽车·毕业设计·毕设
Flynn Liang1 小时前
LangChain4j 生产级工程骨架:12 个模块 + Docker 一键启动
java·spring boot·langchain·rag·langchain4j
噢,我明白了2 小时前
JAVA中的一些基础应用知识点
java·开发语言
寂寞的船2 小时前
【Unity知识速递】第10期 Unity GC 零分配实战:从 UnityEngine.Pool 到手动 GC 控制的全链路优化
jvm·unity·c#·游戏引擎·lucene
SL_staff3 小时前
私有化低代码不是妥协,而是企业级数字化的自主可控主航道
java
装不满的克莱因瓶3 小时前
【SpringAI Alibaba】ReactAgent结构化输出OutputType与OutputSchema实战
java·人工智能·ai·springai·springaialibaba
秋天的怀念_David3 小时前
算法一千零一夜 · 第二十八夜 注册
java·程序人生·算法
Java码农也是农3 小时前
Spring 事务详解:@Transactional 如何生效、何时回滚、传播行为怎么选
java·spring boot·spring·事务
学长毕设4 小时前
基于SpringBoot的游乐园管理系统-附源码
java·spring boot·后端
SimonKing5 小时前
震惊:怎么回事,opencode一轮对话耗尽免费额度
java·后端·程序员