news 2026/4/18 14:53:25

Java多线程:synchronized与Lock的优劣对比

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java多线程:synchronized与Lock的优劣对比

文章目录

  • Java多线程:synchronized与Lock的优劣对比 ?
    • 一、synchronized:Java老炮的同步利器
      • 1.1 synchronized的基本用法
        • **方法级别锁**
        • **代码块级别锁**
      • 1.2 synchronized的优缺点
        • **优点**
        • **缺点**
    • 二、Lock:灵活的同步忍者
      • 2.1 Lock的基本用法
        • **使用ReentrantLock**
        • **使用ReentrantReadWriteLock**
      • 2.2 Lock的优缺点
        • **优点**
        • **缺点**
    • 三、synchronized与Lock的对比总结
    • 四、什么时候该用谁?
      • 4.1 synchronized的适用场景
      • 4.2 Lock的适用场景
    • 五、闫工的肺腑之言
    • 好了,今天就聊到这里。如果你有任何问题或者想了解更多细节,欢迎随时交流!
      • 📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!

Java多线程:synchronized与Lock的优劣对比 ?

大家好!我是闫工,今天要和大家聊一个Java多线程编程中绕不开的话题——synchronized关键字Lock接口的优劣对比。这两个工具在处理并发控制时各有所长,但有时候选择不当可能会让你的代码变得像一团乱麻,性能也跟着“起飞”。所以,今天我们就来仔细分析一下它们之间的区别,看看在什么情况下该用谁。


一、synchronized:Java老炮的同步利器

先说说synchronized关键字吧。这个玩意儿是Java自带的,从JDK1.0就开始服役了,属于Java世界的“老人设”。它简单易用,语法糖的味道很浓,适合那些“懒癌晚期”的开发者。

1.1 synchronized的基本用法

使用synchronized很简单,基本上就是两种方式:

方法级别锁
publicclassSyncExample{publicsynchronizedvoidmethod(){// 加锁的是当前实例对象// 同步代码块}publicstaticsynchronizedvoidstaticMethod(){// 加锁的是类对象// 同步代码块}}
代码块级别锁
publicclassSyncExample{privatefinalObjectlock=newObject();publicvoidmethod(){synchronized(lock){// 使用自定义对象作为锁// 同步代码块}}}

1.2 synchronized的优缺点

优点
  • 简单易用:语法糖的味道很浓,写起来方便。
  • 自动释放锁:当线程执行完同步代码块或者方法时,锁会自动释放,不会出现忘记解锁的情况(当然,如果抛出异常可能会有影响)。
  • 支持可重入:同一个线程可以多次获取同一把锁,不会有死锁的风险。
缺点
  • 粒度较粗synchronized只能在方法级别或者代码块级别加锁,灵活性有限。有时候我们需要更细粒度的控制,这时候synchronized就有点力不从心了。
  • 性能问题synchronized在高并发场景下性能较差,因为它使用的是Java虚拟机内部的监视器(monitor),锁竞争激烈时容易导致线程阻塞和调度开销增加。
  • 无法中断等待:当一个线程正在等待获取synchronized锁时,如果需要停止这个线程,是无法中断的,只能让其自然完成。

二、Lock:灵活的同步忍者

接下来,我们来看看Lock接口。Lock是Java 5引入的一个更高级的同步工具,它提供了比synchronized更灵活的控制能力,同时也需要更多的代码量来实现。

2.1 Lock的基本用法

Lock接口的主要实现类有ReentrantLockReentrantReadWriteLock。我们先来看一个简单的例子:

使用ReentrantLock
importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;publicclassLockExample{privatefinalLocklock=newReentrantLock();publicvoidmethod(){lock.lock();// 获取锁try{// 同步代码块}finally{lock.unlock();// 释放锁}}}
使用ReentrantReadWriteLock
importjava.util.concurrent.locks.ReadWriteLock;importjava.util.concurrent.locks.ReentrantReadWriteLock;publicclassReadWriteLockExample{privatefinalReadWriteLockreadWriteLock=newReentrantReadWriteLock();publicvoidreadMethod(){readWriteLock.readLock().lock();// 读锁try{// 读操作}finally{readWriteLock.readLock().unlock();}}publicvoidwriteMethod(){readWriteLock.writeLock().lock();// 写锁try{// 写操作}finally{readWriteLock.writeLock().unlock();}}}

2.2 Lock的优缺点

优点
  • 灵活控制Lock提供了更细粒度的控制,支持读写锁分离(如ReentrantReadWriteLock),适合高并发场景。
  • 可中断等待:通过lockInterruptibly()方法,可以中断正在等待获取锁的线程。
  • 支持超时:可以通过tryLock(long timeout, TimeUnit unit)方法设置等待时间,避免无限期等待。
缺点
  • 代码复杂度高:需要手动管理锁的获取和释放,容易出现忘记释放锁的情况,导致死锁或者资源泄漏。
  • 性能开销:虽然比synchronized灵活,但它的实现基于操作系统层面的互斥原语,相比synchronized在某些场景下性能可能更差。

三、synchronized与Lock的对比总结

接下来,我们用一张表格来总结一下两者的优缺点:

特性synchronizedLock
语法复杂度简单(语法糖)较复杂(需要手动管理锁)
灵活性粒度较粗(方法或代码块级别)粒度更细,支持读写锁分离
性能低并发场景下较好,高并发场景下较差高并发场景下表现更好,但实现复杂度增加
中断能力不支持中断支持中断(lockInterruptibly()
超时控制不支持支持(tryLock(timeout)
可重入性支持支持

四、什么时候该用谁?

4.1 synchronized的适用场景

  • 当你的同步需求比较简单,不需要复杂的控制逻辑时。
  • 当你需要一个简单且快速实现的解决方案时。
  • 当你不太关注锁的粒度和性能优化时。

例子:

publicclassCounter{privateintcount=0;publicsynchronizedvoidincrement(){count++;}}

4.2 Lock的适用场景

  • 当你需要更细粒度的控制,比如读写锁分离。
  • 当你在高并发场景下需要更好的性能表现。
  • 当你希望支持中断和超时等待的功能。

例子:

publicclassCache{privatefinalReadWriteLocklock=newReentrantReadWriteLock();publicObjectget(Stringkey){lock.readLock().lock();try{// 读取缓存}finally{lock.readLock().unlock();}}publicvoidput(Stringkey,Objectvalue){lock.writeLock().lock();try{// 更新缓存}finally{lock.writeLock().unlock();}}}

五、闫工的肺腑之言

最后,我想说一点:工具的选择永远要看场景synchronized简单粗暴,适合“懒人”;而Lock灵活多变,适合“工匠”。如果你的需求很简单,就不要为了追求复杂而去用Lock;如果你的场景很复杂,也不要为了偷懒不去用Lock

另外,无论你选择哪种方式,都要记得以下几点:

  1. 一定要释放锁:无论是synchronized还是Lock,都可能导致死锁或资源泄漏。
  2. 尽量减少锁的粒度:锁的范围越小,性能越好。
  3. 不要滥用同步:过多的同步会导致线程竞争,反而降低性能。

好了,今天就聊到这里。如果你有任何问题或者想了解更多细节,欢迎随时交流!

📚 领取 | 1000+ 套高质量面试题大合集(无套路,闫工带你飞一把)!

成体系的面试题,无论你是大佬还是小白,都需要一套JAVA体系的面试题,我已经上岸了!你也想上岸吗?

闫工精心准备了程序准备面试?想系统提升技术实力?闫工精心整理了1000+ 套涵盖前端、后端、算法、数据库、操作系统、网络、设计模式等方向的面试真题 + 详细解析,并附赠高频考点总结、简历模板、面经合集等实用资料!

✅ 覆盖大厂高频题型
✅ 按知识点分类,查漏补缺超方便
✅ 持续更新,助你拿下心仪 Offer!

📥免费领取👉 点击这里获取资料

已帮助数千位开发者成功上岸,下一个就是你!✨

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 4:00:01

从冷启动到爆品:AliBoost 如何破解推荐系统“富者愈富”困局

在大规模推荐系统中,如何让新商品、新内容获得公平成长机会,始终是一项核心挑战。 现实中,大多数平台采用“自然推荐 用户行为反馈”的机制:系统根据历史点击、转化等信号,不断强化对高表现商品的推荐权重。然而&…

作者头像 李华
网站建设 2026/4/18 10:50:16

MyBatis体系结构与工作原理 下篇

能力有限,只能粗看核心处理层ORM反射模块如何看public class Reflector {}每一个Reflector对应一个java类简化反射操作ReflectorFactory-创建ReflectorReflector 缓存测试反射的invokermetaclass争对复杂表达式操作metaObject争对对象表达式解析操作从mybatis角度看…

作者头像 李华
网站建设 2026/4/18 10:07:48

LeetCode热题100--136. 只出现一次的数字--简单

题目 给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。 示例 1 : 输入&…

作者头像 李华
网站建设 2026/4/18 8:07:55

“死了么” 改名,申请注册商标注意避开负面词!

近日,在互联网引起网友热议的APP“死了么” 发布消息,称“死了么”将改名“Demumu”,这个应用的核心功能是,用户每日签到,若连续2日未签到则系统次日向紧急联系人发送邮件提醒,普推知产商标老杨认为这个改名…

作者头像 李华
网站建设 2026/4/18 7:43:48

【FFmpeg使用指南】Part 1:核心架构与媒体流处理

📚 写给开发者的音视频处理工程手册 🎯 目标:以严谨的技术视角,解析 FFmpeg 这一跨平台多媒体框架的底层逻辑与工作流。不堆砌参数,而是从原理层面理解“编解码”与“封装”的本质。 🛠️ 核心问题&#xf…

作者头像 李华