synchronized 和 ReentrantLock 怎么选
synchronized 是 Java 并发中最常用也最容易被误解的关键字。从早期的重量级锁到现在的锁升级机制,JVM 对它做了很多优化。本文从底层原理到实际使用,把关键细节讲清楚。
先建立一个最小案例
并发问题不要一开始就上复杂业务。可以先准备一个计数器场景:
class Counter { |
这段代码在单线程里没有问题,但多线程同时调用 add() 时,count++ 不是原子操作,结果可能比预期小。
正确处理思路
如果只是简单计数,可以用 AtomicInteger:
class Counter { |
如果临界区里有多步业务逻辑,可以考虑 synchronized 或 ReentrantLock。选择时不要只看性能,先看代码是否清晰、锁范围是否足够小、异常时是否能释放锁。
排查建议
线上并发问题通常不稳定复现。可以先看日志里是否有重复请求、状态覆盖、库存扣减异常,再用压测或单元测试构造并发场景。
核心要点
synchronized 可以修饰方法或代码块,前者锁对象实例,后者锁指定对象
锁升级过程:无锁 → 偏向锁 → 轻量级锁 → 重量级锁
锁消除和锁粗化是 JVM 的优化手段
synchronized 保证原子性、可见性和有序性
总结
synchronized 是 Java 并发的基础,理解它的工作机制很重要。在实际项目中,合理使用 synchronized 可以保证线程安全,但也要注意锁的粒度。