synchronized 不适合大规模并发,本质是对象级互斥锁,仅保证单线程执行临界区,无法限流、超时或非阻塞获取;高并发下应改用 semaphore、线程池、无锁结构或分片隔离。

synchronized 本身不擅长应对大规模线程并发访问——它本质是串行化工具,不是并发控制器。想靠它“扛住高并发”,容易误用、卡死、拖慢整体吞吐。真正要处理大规模并发场景,得先认清它的定位,再搭配更合适的机制。
明确 synchronized 的真实能力边界
synchronized 是对象级互斥锁,核心作用只有一个:保证同一时刻最多一个线程执行某段代码。它不具备以下能力:
- 控制并发线程数量(比如限制最多 5 个线程同时运行)
- 设置超时等待或可中断的获取锁逻辑
- 支持公平调度或尝试非阻塞加锁
- 在 I/O 或长耗时操作中保持高效(会把其他线程长时间堵在门口)
如果直接用 synchronized 包裹数据库批量写入、远程调用或文件读写等操作,大量线程会在锁外排队,CPU 利用率低、响应延迟飙升,反而让系统更脆弱。
大规模并发下应避免的典型误用
这些写法在高并发时极易成为性能瓶颈甚至死锁诱因:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 锁整个方法且实例共享不足:比如 public synchronized void process() {...},但每个请求都 new 一个新对象,锁根本不起作用;若共用一个对象,又变成全局串行
- 锁粒度过粗:用 this 或类锁保护大段含网络/磁盘操作的逻辑,导致无关线程互相阻塞
- 在 synchronized 块内调用外部服务:一次 RPC 耗时 200ms,100 个线程排队,平均等待时间可能达数秒
- 嵌套锁 + 不同顺序获取:两个线程分别按 A→B 和 B→A 顺序申请锁,触发死锁
面向高并发的合理替代或组合方案
当面临数百甚至上千线程争抢资源时,推荐按需选用以下方式:
- 用 Semaphore 控制并发度:new Semaphore(10) 可稳定放行最多 10 个线程执行关键操作,其余线程等待许可,比 synchronized 更精准、更可控
- 用线程池统一调度:如 Executors.newFixedThreadPool(8),把任务提交进队列,由固定线程数消费,天然限流+复用资源
- 读多写少场景优先用无锁结构:ConcurrentHashMap、LongAdder、CopyOnWriteArrayList 等能显著减少锁竞争
- 业务上做分片隔离:按用户 ID、订单号 hash 分桶,让不同线程操作不同数据分区,从源头避免争抢同一把锁
什么时候还能用 synchronized?
它没被淘汰,只是适用场景很窄。适合以下情况:
- 临界区极小(如更新一个 int 计数器、修改布尔开关标志)
- 并发线程数有限(
- 需要与 wait()/notify() 配合实现简单线程协作(如生产者-消费者模型的小规模版本)
- 作为兜底保护,配合更高级机制使用(例如在 ReentrantLock 获取失败后,降级为 synchronized 保底)
只要不把它当成“高并发万能解药”,就能用得稳、用得准。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










