【Java踩坑笔记】25_synchronized和ReentrantLock该怎么选?
2026/7/5 13:58:26 网站建设 项目流程

25 | synchronized 和 ReentrantLock 该怎么选?

摘要synchronized是 JVM 内置锁,简单易用;ReentrantLock是 Java 代码实现的锁,功能更强大。本文讲清两者的区别和选型原则。


一、问题现象

很多人不知道该用哪个:

// 方式一:synchronizedpublicvoidprocess(){synchronized(this){// 业务逻辑}}// 方式二:ReentrantLockprivatefinalReentrantLocklock=newReentrantLock();publicvoidprocess(){lock.lock();try{// 业务逻辑}finally{lock.unlock();}}

到底该用哪个?


二、踩坑现场

场景 1:需要超时获取锁,synchronized 做不到

// ❌ synchronized 无法设置超时,会一直等publicvoidprocess(){synchronized(this){// 如果锁被占住,会一直阻塞}}

场景 2:需要可中断的锁等待

// ❌ synchronized 的等待无法被中断publicvoidprocess(){synchronized(this){// 线程在等锁的过程中,无法被 interrupt() 唤醒}}

场景 3:需要公平锁

// ❌ synchronized 不保证公平性(抢锁)// 某些场景下需要公平锁(先到先得)

三、原理解析

3.1 synchronized 的特点

优势

  • JVM 内置,自动加锁/释放锁(不需要手动unlock()
  • JDK 1.6 之后做了大量优化(偏向锁、轻量级锁、自旋锁),性能已接近ReentrantLock
  • 代码简洁

劣势

  • 无法设置超时
  • 无法中断等待
  • 不支持公平锁
  • 只支持独占锁(不支持共享锁)
  • 锁的范围只能是代码块或方法

3.2 ReentrantLock 的特点

优势

  • 支持超时获取锁tryLock(timeout, unit)
  • 支持可中断lockInterruptibly()
  • 支持公平锁(构造时传true
  • 支持多条件变量newCondition()
  • 可以尝试获取锁(tryLock(),不阻塞)

劣势

  • 必须手动unlock()(忘了就会死锁)
  • 代码比synchronized

3.3 功能对比表

功能synchronizedReentrantLock
自动释放锁❌(需手动)
超时获取锁tryLock(timeout)
可中断lockInterruptibly()
公平锁new ReentrantLock(true)
多条件变量❌(只有一个隐式条件)newCondition()
尝试获取锁(不阻塞)tryLock()
性能JDK 1.6+ 已优化,接近略好(高并发下)

四、正确写法

4.1 简单场景:用 synchronized

// ✅ 推荐:简单场景用 synchronizedpublicclassCounter{privateintcount=0;publicsynchronizedvoidincrement(){// 锁的是 thiscount++;}publicintgetCount(){returncount;// 读也需要加锁(保证可见性)}}

4.2 需要超时:用 ReentrantLock

// ✅ 推荐:需要超时用 ReentrantLockpublicclassResource{privatefinalReentrantLocklock=newReentrantLock();publicvoidprocess(){try{if(lock.tryLock(5,TimeUnit.SECONDS)){// ✅ 最多等 5 秒try{// 业务逻辑}finally{lock.unlock();// ✅ 必须手动释放}}else{log.warn("获取锁超时");}}catch(InterruptedExceptione){Thread.currentThread().interrupt();// ✅ 恢复中断标志}}}

4.3 需要可中断:用 lockInterruptibly()

// ✅ 推荐:需要可中断用 lockInterruptibly()publicvoidprocess(){try{lock.lockInterruptibly();// ✅ 可以被 interrupt() 唤醒try{// 业务逻辑}finally{lock.unlock();}}catch(InterruptedExceptione){log.info("任务被中断");Thread.currentThread().interrupt();}}

4.4 生产者-消费者:用 Condition

// ✅ 推荐:需要多条件变量用 ConditionpublicclassBlockingQueue<T>{privatefinalList<T>queue=newArrayList<>();privatefinalintmaxSize;privatefinalReentrantLocklock=newReentrantLock();privatefinalConditionnotEmpty=lock.newCondition();privatefinalConditionnotFull=lock.newCondition();publicvoidput(Titem)throwsInterruptedException{lock.lock();try{while(queue.size()==maxSize){notFull.await();// ✅ 等待"不满"条件}queue.add(item);notEmpty.signal();// ✅ 唤醒"不空"的等待线程}finally{lock.unlock();}}publicTtake()throwsInterruptedException{lock.lock();try{while(queue.isEmpty()){notEmpty.await();// ✅ 等待"不空"条件}Titem=queue.remove(0);notFull.signal();// ✅ 唤醒"不满"的等待线程returnitem;}finally{lock.unlock();}}}

五、最佳实践

✅ synchronized vs ReentrantLock 选型指南

场景推荐方案原因
简单的互斥synchronized代码简洁,自动释放锁
需要超时ReentrantLock.tryLock(timeout)synchronized不支持
需要可中断ReentrantLock.lockInterruptibly()synchronized不支持
生产者-消费者ReentrantLock+Condition多条件变量
读多写少ReentrantReadWriteLock读写分离,读读不互斥

🔍 JDK 1.6 之后的 synchronized 优化

JDK 1.6 对synchronized做了大量优化,引入了:

  • 偏向锁:第一个获取锁的线程,后续无需 CAS
  • 轻量级锁:短时间竞争用 CAS,不阻塞线程
  • 自旋锁:获取锁失败时短暂自旋,避免挂起线程
  • 重量级锁:长时间竞争才升级为操作系统互斥量

结论:JDK 1.6+,synchronized性能已接近ReentrantLock,优先用synchronized(代码简洁)。

🛠️ 读写分离场景:用 ReadWriteLock

// ✅ 读多写少场景:用 ReadWriteLockprivatefinalReadWriteLockrwLock=newReentrantReadWriteLock();privatefinalLockreadLock=rwLock.readLock();privatefinalLockwriteLock=rwLock.writeLock();publicStringgetConfig(Stringkey){readLock.lock();// ✅ 多读并发try{returnconfig.get(key);}finally{readLock.unlock();}}publicvoidsetConfig(Stringkey,Stringvalue){writeLock.lock();// ✅ 写独享try{config.put(key,value);}finally{writeLock.unlock();}}

六、小结

  • 简单互斥用synchronized(JDK 1.6+ 性能已够好,代码简洁)
  • 需要超时/可中断/公平锁/多条件变量,用ReentrantLock
  • 读多写少用ReentrantReadWriteLock(读读并发)
  • ReentrantLock必须手动unlock(),放在finally
  • 不确定用哪个?优先synchronized,需要高级功能再换ReentrantLock

第三辑完。—— 下一篇进入第四辑:JVM 与性能篇,首篇:toString里打印对象?小心无限递归栈溢出。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询