新知识点背诵
蚂蚁面试一面复习策略
Lock
基于抽象队列同步AQS(CAS+队列)实现的,是java并发包提供的API
相比于 synchronized
:
可以尝试获取锁(
tryLock()
)可以响应中断(
lockInterruptibly()
)可以实现公平锁 / 非公平锁
可以实现读写分离、条件等待等复杂并发控制
实现类 | 特点 | 使用场景 |
---|---|---|
ReentrantLock | 可重入互斥锁,支持公平 / 非公平两种模式 | 最常用的通用独占锁 |
ReentrantReadWriteLock | ReentrantReadWriteLock.ReadLock内部类,表示读锁 ReentrantReadWriteLock.WriteLock内部类,表示写锁 读写分离锁:允许多个读线程并行,写线程互斥 | 读多写少的场景:缓存读多写少,例如配置中心、热点数据访问。写锁优先可配置(防止写饥饿) |
StampedLock(Java 8+) | 乐观读锁 + 悲观写锁结合,高性能读写锁。但不可重入! | 高并发下读多写少场景(如缓存) |
跨域单点登录
单点登录SSO:指的是用户在多个系统之间切换时,只需要登录一次,就可以访问所有系统,无需重复登录。
两个域名,一个是a.com,一个是b.com,我要实现,我要实现的一个逻辑是说,a.com和b.com他们要相互登录,比如我在a上登录了过后,我可以直接访问b,我在b上面登录过后,我可以直接访问a,那这样一个系统我要怎么样去设置它的相关登录?
核心问题:浏览器的cookie是域隔离的,也就是a.com的cookie无法在b.com使用
核心思路:
同域:Cookie 共享法,让他们同属于一个顶级域名,所有子域共享同一个登录状态
异域:Token + 认证中心(主流做法)-->
统一认证中心:一个独立的后端服务,一般部署在单独域名
用户在a.com登录后,认证中心生成JWT Token签发给用户,同时存入redis(用于控制有效期与登出失效)。b.com 检测到用户未登录,跳转至认证中心(附带自己的回调地址)。认证中心检测到用户已登录(Redis 中 Token 有效)直接生成临时授权码(Code),重定向回 b.com。b.com 使用 Code 向认证中心换取 JWT Token,b.com 本地保存 Token,实现免登录。
浏览器的同源策略 是根本障碍(不同域名之间默认无法共享 Cookie 或进行某些请求)。
反向代理转发(Nginx 代理):前端仍访问
a.com
,Nginx 将请求代理转发到b.com
,浏览器认为仍是同源请求。JWT + 认证中心(适用于不同主域)
WebSocket: 由于 WebSocket 是一种基于消息的双向通信协议,在建立连接时并没有受到跨域限制,因此可以通过 WebSocket 进行跨域通信。
ReentrantLock、Synchronized的区别
对比项 | synchronized | ReentrantLock |
---|---|---|
所属 | JVM 内置关键字 | Java 层实现 |
实现原理 | 基于 对象监视器 和 Mark Word 锁标志位 | 基于 AQS 队列同步器 |
锁类型 | 非公平锁(默认),自适应优化 | 可选公平锁或非公平锁 |
释放锁 | 自动释放(异常时也会释放) | 需要手动释放(lock() / unlock() ) |
可重入性 | 可重入 | 可重入 |
可中断性 | 不可中断 | 可中断(lockInterruptibly() ) |
条件变量 | 单一(wait/notify ) | 多条件队列(Condition ) |
性能优化 | JVM 层面锁优化(偏向锁、轻量级锁、自旋锁) | AQS 的自旋 + CAS + 队列唤醒机制 |
在早期 JDK 版本中,synchronized 是重量级锁,性能差; 而 ReentrantLock 基于 AQS + CAS 实现,性能更高。
但自从 JDK1.6 起,HotSpot 对 synchronized 进行了锁升级优化(偏向锁、轻量级锁、自旋锁),大部分场景下性能已接近甚至优于 ReentrantLock。
不同的是,ReentrantLock 支持可中断、公平锁、多条件变量,适合复杂并发场景; 而 synchronized 语法更简单、安全,推荐在一般同步场景使用。
Spring AOP 是基于动态代理机制实现的。Spring 会在运行时(runtime)为目标对象创建一个“代理对象”, 所有被增强的方法调用,都会经过这个代理对象,从而实现“在方法执行前后织入额外逻辑”。
对于实现了接口的类,Spring 使用 JDK 动态代理; 对于没有接口的类,则使用 CGLIB 字节码增强技术生成子类代理。
注解与后置处理器机制:Spring 在启动时通过
@Aspect
注解和AnnotationAwareAspectJAutoProxyCreator
后置处理器识别哪些 Bean 需要切面增强, 并在 Bean 初始化阶段创建代理对象,将切面逻辑织入到方法调用链中。运行时调用时,代理对象拦截方法,按切点匹配的顺序执行
@Before
、@After
等增强逻辑,最终完成 AOP 的动态织入。
用户调用代理对象的目标方法;
Spring AOP 代理拦截调用;
AOP 框架根据切点表达式匹配所有符合条件的切面;
将这些切面按优先级组成一个 责任链(Interceptor Chain);
按顺序执行:
@Before
→ 调用目标方法 →@AfterReturning
/@AfterThrowing
→@After
整个过程完全是运行时动态织入,而不是像 AspectJ 那样的编译期静态织入。