shiro中synchronized不直接用于权限验证或会话管理核心逻辑,因其自身采用concurrenthashmap、threadlocal隔离、无状态过滤器等线程安全设计;误用会导致性能瓶颈或死锁,真需同步时应优先选用juc工具或细粒度锁。
在shiro中,synchronized一般**不直接用于权限验证或会话管理的核心逻辑**,shiro自身已通过线程安全设计(如使用concurrenthashmap、无状态过滤器、可重入的subject绑定机制)规避了多数并发问题。强行在自定义会话管理器中滥用synchronized,反而容易引发性能瓶颈甚至死锁。
Shiro会话管理本身是线程安全的
Shiro默认的DefaultSessionManager和内存型MemorySessionDAO内部已采用线程安全结构:
- 会话存储(如
ConcurrentHashMap)天然支持高并发读写 - 每个
Subject绑定独立Session实例,不同请求间无共享状态冲突 -
SessionKey基于ThreadLocal或SecurityManager上下文隔离,不依赖方法级同步
哪些场景可能误加synchronized?
开发者常在以下自定义扩展中不必要地加锁:
- 重写
SessionDAO时,在readSession()或update()方法上加synchronized——实际应依赖底层存储(如Redis、数据库)的原子性或分布式锁 - 在
AuthorizingRealm的doGetAuthorizationInfo()里同步整个方法——该方法本就按Subject隔离,无需同步;若访问共享缓存,应只对缓存操作加锁(且优先用ConcurrentMap.computeIfAbsent()) - 自定义
SessionListener中对统计计数器加锁——可用AtomicLong替代
真需要同步时,推荐更优方案
若业务确需保护共享资源(如本地会话ID生成器、单机限流计数),应避免粗粒度synchronized方法:
- 用细粒度锁:对具体对象(如
private final Object lock = new Object();)加锁,而非this或类锁 - 用JUC工具:
ReentrantLock支持超时与中断,StampedLock适合读多写少场景 - 分布式环境必须放弃
synchronized:改用Redis的SETNX、ZooKeeper临时节点或成熟框架(如Redisson)
Shiro权限验证过程无需手动加锁
标准流程(Subject.isPermitted() → AuthorizingRealm → 缓存/DB查询)天然无竞态:
- 权限检查结果通常缓存在
Subject或CacheManager中,缓存实现(如Ehcache、Caffeine)本身线程安全 - 即使缓存未命中,每次查询都是独立数据库/服务调用,不共享中间状态
- 若自定义逻辑涉及静态变量或单例资源,应确保该资源本身线程安全,而非包裹
synchronized
不复杂但容易忽略:Shiro的设计哲学是“让并发问题由底层存储和JVM工具解决,而非框架层硬同步”。关注锁的粒度、范围和分布一致性,比盲目加synchronized重要得多。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











