作者 | 磊哥

来源 | Java面试真题解析(ID:aimianshi666)

转载请联系授权(微信ID:GG_Stone)

在 Java 中,常用的锁有两种:synchronized(内置锁)和 ReentrantLock(可重入锁),二者的功效都是相同得,但又有很多不同点,所以我们今天就来聊聊。

区别1:用法不同

synchronized 可用来修饰普通方法、静态方法和代码块,而 ReentrantLock 只能用在代码块上。

synchronized 基础使用

使用 synchronized 修饰代码块:

public void method() {// 加锁代码synchronized (this) {// ...}
}

ReentrantLock 基础使用

ReentrantLock 在使用之前需要先创建 ReentrantLock 对象,然后使用 lock 方法进行加锁,使用完之后再调用 unlock 方法释放锁,具体使用如下:

public class LockExample {// 创建锁对象private final ReentrantLock lock = new ReentrantLock();public void method() {// 加锁操作lock.lock();try {// ...} finally {// 释放锁lock.unlock();}}
}

区别2:获取锁和释放锁方式不同

synchronized 会自动加锁和释放锁,当进入 synchronized 修饰的代码块之后会自动加锁,当离开 synchronized 的代码段之后会自动释放锁,如下图所示:而 ReentrantLock 需要手动加锁和释放锁,如下图所示:

PS:在使用 ReentrantLock 时要特别小心,unlock 释放锁的操作一定要放在 finally 中,否者有可能会出现锁一直被占用,从而导致其他线程一直阻塞的问题。

区别3:锁类型不同

synchronized 属于非公平锁,而 ReentrantLock 既可以是公平锁也可以是非公平锁。默认情况下 ReentrantLock 为非公平锁,这点查看源码可知:使用 new ReentrantLock(true) 可以创建公平锁,查看源码可知:

区别4:响应中断不同

ReentrantLock 可以使用 lockInterruptibly 获取锁并响应中断指令,而 synchronized 不能响应中断,也就是如果发生了死锁,使用 synchronized 会一直等待下去,而使用 ReentrantLock 可以响应中断并释放锁,从而解决死锁的问题,比如以下 ReentrantLock 响应中断的示例:

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockInterrupt {static Lock lockA = new ReentrantLock();static Lock lockB = new ReentrantLock();public static void main(String[] args) throws InterruptedException {// 线程 1:先获取 lockA 再获取 lockBThread t1 = new Thread(() -> {try {// 先获取 LockAlockA.lockInterruptibly();// 休眠 10 毫秒TimeUnit.MILLISECONDS.sleep(100);// 获取 LockBlockB.lockInterruptibly();} catch (InterruptedException e) {System.out.println("响应中断指令");} finally {// 释放锁lockA.unlock();lockB.unlock();System.out.println("线程 1 执行完成。");}});// 线程 2:先获取 lockB 再获取 lockAThread t2 = new Thread(() -> {try {// 先获取 LockBlockB.lockInterruptibly();// 休眠 10 毫秒TimeUnit.MILLISECONDS.sleep(100);// 获取 LockAlockA.lockInterruptibly();} catch (InterruptedException e) {System.out.println("响应中断指令");} finally {// 释放锁lockB.unlock();lockA.unlock();System.out.println("线程 2 执行完成。");}});t1.start();t2.start();TimeUnit.SECONDS.sleep(1);// 线程1:执行中断t1.interrupt();}
}

以上程序的执行结果如下所示:

区别5:底层实现不同

synchronized 是 JVM 层面通过监视器(Monitor)实现的,而 ReentrantLock 是通过 AQS(AbstractQueuedSynchronizer)程序级别的 API 实现。synchronized 通过监视器实现,可通过观察编译后的字节码得出结论,如下图所示:其中 monitorenter 表示进入监视器,相当于加锁操作,而 monitorexit 表示退出监视器,相当于释放锁的操作。ReentrantLock 是通过 AQS 实现,可通过观察 ReentrantLock 的源码得出结论,核心实现源码如下:

小结

synchronized 和 ReentrantLock 都是 Java 中提供的可重入锁,二者的主要区别有以下 5 个:

  1. 用法不同:synchronized 可以用来修饰普通方法、静态方法和代码块,而 ReentrantLock 只能用于代码块。

  2. 获取锁和释放锁的机制不同:synchronized 是自动加锁和释放锁的,而 ReentrantLock 需要手动加锁和释放锁。

  3. 锁类型不同:synchronized 是非公平锁,而 ReentrantLock 默认为非公平锁,也可以手动指定为公平锁。

  4. 响应中断不同:ReentrantLock 可以响应中断,解决死锁的问题,而 synchronized 不能响应中断。

  5. 底层实现不同:synchronized 是 JVM 层面通过监视器实现的,而 ReentrantLock 是基于 AQS 实现的。

是非审之于己,毁誉听之于人,得失安之于数。

公众号:Java面试真题解析

面试合集:https://gitee.com/mydb/interview

往期推荐

每周汇总 | Java面试题(共41篇)2022版

面试突击41:notify是随机唤醒吗?

面试突击40:线程休眠的方法有几种?

synchronized和ReentrantLock的5个区别!相关推荐

  1. java 同步方式 lock_java的两种同步方式, Synchronized与ReentrantLock的区别

    java在编写多线程程序时,为了保证线程安全,需要对数据同步,经常用到两种同步方式就是Synchronized和重入锁ReentrantLock. 相似点: 这两种同步方式有很多相似之处,它们都是加锁 ...

  2. synchronized和ReentrantLock区别浅析 (转载地址:http://blog.csdn.net/zmx729618/article/details/51594166)

    一.什么是sychronized sychronized是java中最基本同步互斥的手段,可以修饰代码块,方法,类. 在修饰代码块的时候需要一个reference对象作为锁的对象. 在修饰方法的时候默 ...

  3. 【每日一题~001】谈谈synchronized与ReentrantLock的区别?

    每日一题,共同成长,见证奇迹,加油老铁 问题:谈谈synchronized与ReentrantLock的区别?思考:2分钟...答案如下:1.底层实现:1)synchronized 是JVM层面的锁, ...

  4. 【并发编程】线程锁--Synchronized、ReentrantLock(可重入锁)

    在说锁之前,我们要明白为什么要加锁,不加锁会怎样? 在并发编程中,很容易出现线程安全问题,接下来我们看个很经典的例子--银行取钱,来看一下有关线程安全的问题. 取钱的流程可以分为一下几个步骤: 1.用 ...

  5. Java—synchronized和ReentrantLock锁详解

    关注微信公众号:CodingTechWork,一起学习进步. 1 synchronized 1.1 synchronized介绍 synchronized机制提供了对每个对象相关的隐式监视器锁,并强制 ...

  6. reentrantlock原理_分享:synchronized和ReentrantLock的实现原理知识点

    前言 通常呢,会在并发情况下,同时操作某一业务从而造成数据重复提交,业务混乱等问题,通常呢,遇到解决类似问题可采用加锁,限流等问题来解决,那么看看这篇关于java中关于锁中synchronized和R ...

  7. synchronized,ReentrantLock、ReentrantReadWriteLock和StampedLock

    java四种上锁方式原理及适用场景区分 synchronized(monitor).ReentantLock(AQS).AtomicLong(CAS).LongAdder(XADD) 针对代码块需要同 ...

  8. 【Java】synchronized和ReentrantLock分析

    synchronized和ReentrantLock分析 参考: 子路老师博客:https://blog.csdn.net/java_lyvee/article/details/110996764 并 ...

  9. synchronized和ReentrantLock区别

    1.区别: 1)Lock是一个接口,synchronized是Java中的关键字,synchronized是内置的语言实现: 2)synchronized发生异常时,会自动释放线程占用的锁,故不会发生 ...

最新文章

  1. 单轴步进驱动模块SH-20403
  2. 如何用计算机输入数学公式,使用Win7输入面板让数学公式输入更轻松
  3. 报告解读丨细数万亿企服市场发展史,揭秘行业发展新趋势
  4. mysql集群数据引擎_MySQL数据引擎
  5. linux shell 豆瓣,用Linux shell脚本爬取豆瓣邮箱
  6. mysql 自连接 树形_自连接表的相关问题(树形结构)
  7. windows下,‘nmake‘不是内部或外部命令,也不是可运行的程序或批处理文件
  8. 雷布斯被骗200w??一行代码值两百万?雷军公开小米新logo翻车了?
  9. 【IDEA】IDEA中部署的项目添加Tomcat自带的一些项目
  10. mysql buffer size_mysql read_buffer_size 设置多少合适
  11. windows下使用iconv命令批量原地转码文件
  12. winhttp 访问https_「winhttp」C++用winhttp实现https访问服务器 - seo实验室
  13. PGP加密软件使用教程-云安全技术
  14. 在线Markdown table生成工具,Markdown 表格编辑器
  15. 第九届GIS应用技能大赛上午(试题及答案含数据)
  16. Android Things发布新版本DP7,NXP和树莓派开发板可升级
  17. 运行时错误91问题汇总
  18. 磁性微型机器人通过结肠翻筋斗以输送药物
  19. STM32F105RCT6使用CubeMX初始化工程——3:初始化ADC采样
  20. 合法标识符(C语言)

热门文章

  1. IIS Express配置使通过IP访问
  2. 关于人工智能的一些介绍与看法
  3. 腾讯云从业者认证考试(学习笔记知识总结-全部章节)
  4. 第一款个人应用——《不做手机控》——终于上线啦!
  5. 找到组织了---perftest工作室 TIB工作室
  6. matlab 共轭,求解线性方程组 - 双共轭梯度法
  7. openssl 命令行加密解密
  8. 安装gi的时候回退root.sh的执行
  9. 美团王兴,为什么让骑手注册个体户?详解他的套路,望周知
  10. 航姿参考系统(AHRS)