当前位置: 首页 > news >正文

Java中synchronized和ReentrantLock锁重入机制详解

在Java中,锁的重入(Reentrancy)是指同一个线程可以多次获取同一把锁而不会造成死锁的特性。这是Java内置锁(synchronized)和ReentrantLock的一个重要特性。

核心概念

当一个线程已经持有某个锁时,它可以再次请求获取这个锁,JVM会记录锁被同一个线程持有的次数,只有当锁完全释放(计数器归零)时,其他线程才能获取该锁。

synchronized的锁重入示例

publicclassReentrantDemo{publicsynchronizedvoidmethodA(){System.out.println("进入methodA");methodB();// 调用另一个同步方法System.out.println("离开methodA");}publicsynchronizedvoidmethodB(){System.out.println("进入methodB");// 做一些操作System.out.println("离开methodB");}publicstaticvoidmain(String[]args){ReentrantDemodemo=newReentrantDemo();// 同一个线程可以重入锁newThread(()->demo.methodA()).start();}}

输出:

进入methodA 进入methodB 离开methodB 离开methodA

ReentrantLock的锁重入示例

importjava.util.concurrent.locks.ReentrantLock;publicclassReentrantLockDemo{privatefinalReentrantLocklock=newReentrantLock();publicvoidouter(){lock.lock();try{System.out.println("外层方法,锁重入计数: "+lock.getHoldCount());inner();// 调用内层方法,重入锁}finally{lock.unlock();}}publicvoidinner(){lock.lock();try{System.out.println("内层方法,锁重入计数: "+lock.getHoldCount());}finally{lock.unlock();}}publicstaticvoidmain(String[]args){ReentrantLockDemodemo=newReentrantLockDemo();demo.outer();}}

输出:

外层方法,锁重入计数: 1 内层方法,锁重入计数: 2

锁重入的实现机制

1. synchronized的实现

  • JVM为每个锁对象维护一个计数器
  • 当线程第一次获取锁时,计数器=1
  • 每次重入,计数器+1
  • 每次退出同步代码块,计数器-1
  • 计数器归零时,锁完全释放

2. ReentrantLock的实现

  • 使用AQS(AbstractQueuedSynchronizer)的state字段记录重入次数
  • 通过getHoldCount()方法可以获取当前线程的重入次数

为什么需要锁重入?

1.避免死锁

// 如果没有锁重入,这段代码会导致死锁publicclassWithoutReentrancy{publicsynchronizedvoida(){b();// 调用另一个同步方法}publicsynchronizedvoidb(){// 一些操作}}

2.支持面向对象的设计

  • 子类可以重写父类的同步方法
  • 方法可以调用其他同步方法
  • 支持递归调用

锁重入的注意事项

1.释放次数必须匹配

publicclassLockReleaseExample{privatefinalReentrantLocklock=newReentrantLock();publicvoidwrong(){lock.lock();lock.lock();// 重入// 业务逻辑lock.unlock();// 只释放一次,锁没有完全释放!}publicvoidcorrect(){lock.lock();lock.lock();// 重入try{// 业务逻辑}finally{lock.unlock();// 释放一次lock.unlock();// 再释放一次}}}

2.可重入锁 vs 不可重入锁

特性可重入锁不可重入锁
同一线程多次获取允许会导致死锁
实现复杂度较高较低
使用场景大多数情况特定场景
Java示例synchronized, ReentrantLock需要自定义实现

实际应用场景

1.递归调用

publicclassRecursiveExample{publicsynchronizedvoidrecursive(intn){if(n<=0)return;System.out.println("递归深度: "+n);recursive(n-1);// 递归调用,需要锁重入}}

2.模板方法模式

publicabstractclassTemplateMethod{publicfinalvoidtemplateMethod(){synchronized(this){doOperation1();doOperation2();// 可能需要锁保护}}protectedabstractvoiddoOperation1();protectedabstractvoiddoOperation2();}

总结

锁重入是Java并发编程中的重要特性,它:

  1. 提高了灵活性:允许方法调用其他同步方法
  2. 避免了自死锁:同一个线程不会因为重复获取锁而阻塞自己
  3. 简化了编程:开发者不需要担心嵌套同步的问题
  4. 支持面向对象设计:便于继承和多态的实现

Java中的synchronized关键字和ReentrantLock都内置了锁重入机制,这也是为什么它们被称为"可重入锁"的原因。

http://www.jsqmd.com/news/206505/

相关文章:

  • 【心脏病检测】基于matlab GUI检测胎儿心脏病【含Matlab源码 14854期】
  • Java中的锁对象详解
  • 深度学习毕设选题推荐:基于python深度学习的树叶健康识别人工智能
  • Java 对接 PLC 实战:西门子 PLC 与永宏 PLC 通讯方式全面对比
  • 入校申报审批系统的设计与实现毕业论文+PPT(附源代码+演示视频)
  • 化工TPM预防性维护落地指南:从0到1实现故障降40%
  • Katalon StudioAssist:智能化测试助手
  • 一篇讲透:芋道源码中的「租户」是如何通过程序控制的?
  • 凤希AI伴侣开发手记:那些只有深度使用才暴露的“缺点”
  • 计算机深度学习毕设实战-基于python深度学习的树叶健康识别机器学习
  • Memcached vs Redis:面试必看的彻底解析
  • 芋道(Ruoyi-Vue-Pro)对接腾讯云短信:没配回调URL,为啥也能看到发送成功/失败?如何排查?
  • ZGLanguage 解析SQL数据血缘 之 提取子查询语句中的源表名
  • ZGLanguage 解析SQL数据血缘 之 提取子查询语句中的源表名
  • typescript-var和let作用域
  • 2026年香港服务器走CN2线路具有哪些优势?
  • 2026年香港服务器走CN2线路具有哪些优势?
  • 都在做「WAN优化」,南凌科技的方案究竟有何不同?
  • 香港服务器为何需要IPMI?好用吗
  • 彻底解决启动问题:如何修复错误代码0xc000000e一站式教程
  • 云原生ETL方案:AWS Glue vs Azure Data Factory
  • 免费听书神器喜马拉雅v9.4.32.3精简版分享 解锁付费内容 无限畅听
  • 牛批了,Windows搬家神器
  • FTP登陆工具SmartFTP Client Enterprise v10.0.3300 多语便携版下载 FTP文件传输神器
  • Katalon StudioAssist Ask模式:工作区内的AI测试助手
  • 如何打开大文件不崩溃不卡顿?EmEditor v25.4.4绿色便携版下载
  • 敏捷的质量合伙人
  • php+nginx在cookie中设置了HttpOnly属性
  • 2026必备!本科生论文写作软件TOP9测评
  • 黑马反弹抄底之短炒选股指标公式