ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

Synchronized VS ReentrantLock

Synchronized VS ReentrantLock 在 Java 并发编程体系中synchronized内置锁与ReentrantLock显式锁是实现线程同步、保证并发安全的两大核心方案。绝大多数开发者只会表层使用synchronized 简单、ReentrantLock 灵活但完全说不清核心差异为什么 JDK1.6 优化后 synchronized 性能反超 ReentrantLock显式锁灵活在哪里什么场景必须放弃 synchronized 用 ReentrantLock两者的底层锁机制、调度逻辑、并发能力有哪些本质区别一、前置核心认知两大锁的本质定位1.1 synchronizedJVM 原生内置隐式锁synchronized 是 Java 语言原生关键字由 JVM 底层硬编码实现属于隐式锁。锁的获取、释放全部由 JVM 自动管控开发者无需手动干预简单无脑、自动兜底。核心定位极简通用型同步锁主打低学习成本、自动安全、无需手动运维适配绝大多数普通并发场景。1.2 ReentrantLockJDK 代码实现显式锁ReentrantLock 是java.util.concurrent.locks包下的工具类锁基于 AQS抽象队列同步器纯代码实现属于显式锁。锁的获取、释放、调度策略全部由开发者手动编码控制高度灵活。核心定位高阶增强型同步锁主打高灵活性、可定制、强并发能力适配复杂、高并发、精细化管控的业务场景。二、底层实现原理深度拆解最核心差异2.1 synchronized 底层原理JVM 层级锁升级机制JDK1.6 之前synchronized 是笨重的重量级锁依赖操作系统 Mutex 互斥量需要用户态与内核态切换开销极大。JDK1.6 对其进行极致自适应优化引入三级锁升级机制全程自动适配场景无需开发者干预无竞争场景偏向锁零开销、无CAS、无同步操作单线程重复加锁直接放行轻微竞争场景轻量级锁用户态CAS自旋无线程阻塞、无内核切换用少量CPU空转避免阻塞开销激烈竞争场景重量级锁依托操作系统内核互斥量线程阻塞入队牺牲内核开销保证并发稳定核心底层特点锁状态存储在对象头 Mark Word中锁升级单向不可逆全程 JVM 自动调度无人工干预空间。2.2 ReentrantLock 底层原理AQS 独占可重入机制ReentrantLock 从 JDK1.5 诞生之初底层就固定基于AQSAbstractQueuedSynchronizer实现无锁升级机制从始至终都是统一的独占锁模型。核心底层逻辑依托 AQS 的state 状态变量记录锁持有次数实现可重入特性依托 AQS双向阻塞队列完成抢锁失败线程的排队、唤醒、调度原生支持公平锁/非公平锁手动切换默认非公平锁所有锁竞争、排队、唤醒逻辑均为Java 代码层级实现不依赖操作系统内核核心底层特点无自适应锁升级纯用户态代码调度灵活性拉满、可定制性极强但简单场景下冗余逻辑更多。三、核心功能与特性全方位对比3.1 锁的可重入性共同点两者均支持可重入同一个线程获取锁后可重复加锁不会出现自己阻塞自己的死锁问题。synchronizedJVM 底层自动记录重入次数无需手动计数自动解锁ReentrantLock基于 AQS state 变量计数加锁 state1解锁 state-1必须成对解锁3.2 锁释放机制核心差异synchronized隐式释放代码执行完毕、异常抛出时JVM自动释放锁绝对不会出现锁泄露安全性极高ReentrantLock显式释放必须手动在finally 代码块中调用 unlock()释放锁代码异常、忘记释放会直接导致永久锁泄露、线程死锁3.3 公平锁支持synchronized仅支持非公平锁无任何手动配置方式锁释放后随机唤醒等待线程无法保证先来先到ReentrantLock原生双模式支持构造方法传入 true 开启公平锁FIFO排队默认非公平锁可自由切换3.4 锁等待可控性synchronized抢锁失败线程永久阻塞无法超时、无法中断极易出现线程卡死、服务雪崩问题ReentrantLock提供tryLock()超时抢锁、lockInterruptibly()可中断抢锁完全可控从根源规避死锁和永久阻塞3.5 精准唤醒机制synchronized依托 Object 的 wait/notify只能随机唤醒一个线程或全部唤醒无法精准唤醒存在无效唤醒、资源浪费问题ReentrantLock依托Condition 条件队列可创建多个条件队列实现精准分组唤醒按需唤醒指定线程并发效率更高3.6 锁状态可监控synchronized无任何 API 可监控锁状态无法判断是否加锁、是否被占用、等待线程数量排查问题困难ReentrantLock提供丰富监控 APIisLocked()、getQueueLength()、hasWaiters()可实时监控锁状态、线程排队情况便于线上问题排查四、性能差异深度解析架构师必懂4.1 JDK1.6 前后性能反转JDK1.5 及之前synchronized 只有重量级锁内核切换开销巨大性能远差于 ReentrantLockJDK1.6 及之后synchronized 引入自适应锁升级无竞争/轻微竞争场景开销极低整体性能反超 ReentrantLock4.2 不同场景性能表现低竞争、单线程场景synchronized 偏向锁零开销性能优于 ReentrantLockReentrantLock 存在 AQS 代码逻辑冗余开销中等交替竞争场景两者性能持平synchronized 轻量级锁 CAS 自旋与 AQS 调度开销相近高并发激烈竞争场景ReentrantLock 性能更优可通过公平锁、超时机制、精准唤醒减少无效竞争而 synchronized 极易直接升级为重量级锁性能暴跌五、全方位核心差异对比表对比维度Synchronized内置锁ReentrantLock显式锁实现层级JVM 底层原生实现关键字JDK 代码层级实现AQS 工具类锁模式仅非公平锁不可配置公平/非公平锁可手动切换锁释放方式自动释放代码结束/异常安全无泄露手动 unlock() 释放需 finally 兜底易泄露等待可控性不可超时、不可中断永久阻塞支持超时抢锁、可中断抢锁完全可控唤醒机制notify()/notifyAll()随机/全部唤醒无精准控制Condition 精准分组唤醒按需唤醒锁监控能力无监控 API无法排查锁状态丰富监控 API可查看排队、等待线程数底层机制偏向锁→轻量级锁→重量级锁 自适应升级AQS 双向队列 state 计数无锁升级代码简洁度极简一行关键字搞定繁琐需手动加锁、解锁、异常兜底可重入性支持JVM 自动计数兜底支持AQS state 手动计数适用场景低并发、普通同步、简单场景高并发、复杂同步、需要精细化管控场景六、精准选型口诀落地核心6.1 优先选择 Synchronized 的场景选型口诀简单同步、低并发、无需特殊管控一律用 synchronized普通方法、代码块同步逻辑简单并发竞争不激烈单线程/少量线程交替执行追求代码简洁、低维护成本、杜绝锁泄露不需要超时锁、公平锁、精准唤醒等特殊能力架构师思考JDK1.6 后 synchronized 性能足够优秀且自动兜底、零运维简单场景用它性价比最高。6.2 必须选择 ReentrantLock 的场景选型口诀需灵活管控、高并发、防死锁、精准同步必用 ReentrantLock需要公平锁必须保证线程先来先到杜绝线程饥饿需要超时抢锁防止永久阻塞、规避死锁服务容错优先精准线程唤醒生产者消费者、多条件分组等待场景高并发激烈竞争需要稳定可控的锁调度避免锁升级重量级锁雪崩线上锁问题排查需要监控锁状态、线程排队数量七、生产环境高频避坑指南7.1 Synchronized 避坑点禁止同步代码块过长执行耗时过久会导致锁竞争激烈快速升级为重量级锁吞吐量暴跌避免锁对象变更锁对象为变量时对象替换会导致锁失效引发并发安全问题杜绝永久阻塞场景无超时、不可中断特性高并发下易造成线程堆积、服务卡死明确锁范围尽量缩小同步粒度只锁核心共享代码避免大范围锁竞争7.2 ReentrantLock 避坑点必须 finally 解锁绝对禁止忘记 unlock()、异常跳过解锁直接导致锁泄露、死锁tryLock 必须判空不判断抢锁成功状态直接执行业务引发线程安全问题重入锁成对解锁多次加锁必须对应多次解锁否则锁无法释放不滥用公平锁公平锁牺牲性能换顺序无业务需求默认用非公平锁八、全文核心总结1.本质区别synchronized 是 JVM 自动管控的隐式锁主打简单安全、自适应优化ReentrantLock 是代码手动管控的显式锁主打灵活可控、功能强大。2.性能取舍低竞争场景 synchronized 更优高并发复杂场景 ReentrantLock 更稳定JDK1.6 无绝对性能碾压只有场景适配。3.功能取舍synchronized 能力基础够用无高级特性ReentrantLock 拥有超时锁、公平锁、精准唤醒、状态监控等高阶能力适配复杂业务。4.终极选型原则简单场景无脑用 synchronized复杂高并发、需要精细化锁管控场景必用 ReentrantLock绝不反向选型。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表