synchronized 和 ReentrantLock 怎么选

synchronized 和 ReentrantLock 怎么选

synchronized 是 Java 并发中最常用也最容易被误解的关键字。从早期的重量级锁到现在的锁升级机制,JVM 对它做了很多优化。本文从底层原理到实际使用,把关键细节讲清楚。

先建立一个最小案例

并发问题不要一开始就上复杂业务。可以先准备一个计数器场景:

class Counter {
private int count = 0;

public void add() {
count++;
}

public int get() {
return count;
}
}

这段代码在单线程里没有问题,但多线程同时调用 add() 时,count++ 不是原子操作,结果可能比预期小。

正确处理思路

如果只是简单计数,可以用 AtomicInteger

class Counter {
private final AtomicInteger count = new AtomicInteger();

public void add() {
count.incrementAndGet();
}

public int get() {
return count.get();
}
}

如果临界区里有多步业务逻辑,可以考虑 synchronizedReentrantLock。选择时不要只看性能,先看代码是否清晰、锁范围是否足够小、异常时是否能释放锁。

排查建议

线上并发问题通常不稳定复现。可以先看日志里是否有重复请求、状态覆盖、库存扣减异常,再用压测或单元测试构造并发场景。

核心要点

  1. synchronized 可以修饰方法或代码块,前者锁对象实例,后者锁指定对象

  2. 锁升级过程:无锁 → 偏向锁 → 轻量级锁 → 重量级锁

  3. 锁消除和锁粗化是 JVM 的优化手段

  4. synchronized 保证原子性、可见性和有序性

总结

synchronized 是 Java 并发的基础,理解它的工作机制很重要。在实际项目中,合理使用 synchronized 可以保证线程安全,但也要注意锁的粒度。


   转载规则


《synchronized 和 ReentrantLock 怎么选》 小乐 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录