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

面试题:ReentrantLock与synchronized区别

ReentrantLocksynchronized`都是Java中用于实现线程同步的机制,但它们在多个方面存在显著的区别:

1. 实现方式

  • synchronized

    • 是Java语言的关键字,属于原生语法层面的互斥锁。
    • 由JVM实现,不需要显式地获取和释放锁。
  • ReentrantLock

    • 是JDK 1.5之后提供的API层面的互斥锁。
    • 需要通过lock()方法显式地获取锁,并通过unlock()方法显式地释放锁。

2. 锁的获取和释放

  • synchronized

    • 锁的获取和释放是隐式的,编译器会自动在同步块的前后插入monitorentermonitorexit字节码指令。
    • 如果获取锁失败,线程会进入阻塞状态,直到锁被释放。
  • ReentrantLock

    • 锁的获取和释放是显式的,需要手动调用lock()unlock()方法。
    • 为了避免忘记释放锁导致死锁,通常建议在finally块中调用unlock()方法。

3. 锁的公平性

  • synchronized

    • 默认情况下是不公平的,即线程获取锁的顺序是不确定的。
  • ReentrantLock

    • 可以选择公平锁或非公平锁。通过构造函数参数指定是否使用公平锁。
    • 公平锁会按照线程请求锁的顺序来分配锁,但性能相对较低。

4. 锁的粒度

  • synchronized

    • 锁的粒度较粗,一个同步块只能锁定一个对象。
  • ReentrantLock

    • 锁的粒度较细,可以通过tryLock()方法尝试获取锁,如果获取失败可以进行其他操作。
    • 支持多个条件变量(Condition),可以在不同的条件下等待和通知线程。

5. 性能

  • synchronized

    • 在Java 6之后,synchronized进行了大量优化,包括偏向锁、轻量级锁和自旋锁,性能得到了显著提升。
    • 在大多数情况下,synchronized的性能已经足够好。
  • ReentrantLock

    • 提供了更多的灵活性和高级功能,如可中断锁、超时锁等。
    • 在某些特定场景下,ReentrantLock的性能可能优于synchronized,特别是在需要细粒度控制和高级功能的场景下。

6. 可重入性

  • synchronized

    • 是可重入的,即一个线程可以多次获取同一个锁而不会导致死锁。
  • ReentrantLock

    • 也是可重入的,通过内部计数器来记录线程获取锁的次数。

示例代码

synchronized示例
public class SynchronizedExample {private int count = 0;public synchronized void increment() {count++;}public synchronized int getCount() {return count;}
}
ReentrantLock示例
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; public class ReentrantLockExample {private int count = 0;private final Lock lock = new ReentrantLock();public void increment() {lock.lock(); try {count++;} finally {lock.unlock(); }}public int getCount() {lock.lock(); try {return count;} finally {lock.unlock(); }}
}

总结

  • synchronized:简单易用,适用于大多数场景,性能较好。
  • ReentrantLock:灵活性高,适用于需要细粒度控制和高级功能的场景。

选择哪种同步机制取决于具体的应用场景和需求。

http://www.dtcms.com/a/187471.html

相关文章:

  • 2025年RIS SCI2区,改进白鲸优化算法+复杂非线性方程组求解,深度解析+性能实测
  • apache2的默认html修改
  • 【WIN】笔记本电脑忘记密码解决办法/笔记本电脑重装系统笔记/bitlocker忘记密码的解决办法
  • JavaScript异步编程 Async/Await 使用详解:从原理到最佳实践
  • Vue2 elementUI 二次封装命令式表单弹框组件
  • 鸿蒙PC版体验_画面超级流畅_具备terminal_无法安装windows、linux软件--纯血鸿蒙HarmonyOS5.0工作笔记017
  • WPF的UI元素类型详解
  • 飞书配置表数据同步到数据库中
  • Ansys 产品在Windows系统的卸载(2025R1版)
  • BFS算法篇——从晨曦到星辰,BFS算法在多源最短路径问题中的诗意航行(下)
  • 游戏引擎学习第276天:调整身体动画
  • MySQL基础入门:MySQL简介与环境搭建
  • Linux文件编程——标准库函数fopen、fread、fwrite等函数
  • Feign+Resilience4j实现微服务熔断机制:原理与实战
  • 道通EVO MAX系列无人机-支持二次开发
  • 引用传递(c++基础知识)
  • 【HCIA】浮动路由
  • 无人机失联保护模块技术解析!
  • Android设备是否满足硬件要求
  • day19-线性表(顺序表)(链表)
  • Spring 集成 SM4(国密对称加密)
  • 计算机系统----软考中级软件设计师(自用学习笔记)
  • 【TDengine源码阅读】TAOS_DEF_ERROR_CODE(mod, code)
  • Babylon.js学习之路《四、Babylon.js 中的相机(Camera)与视角控制》
  • plus-uiRuoYi-Vue-Plus 基于pgSql本地运行实践
  • 20250512期:基于arcpy数据驱动的大批量规范化出图
  • 从入门到精通:Drools全攻略
  • centos9安装docker 配置docker代理
  • 阿克曼-幻宇机器人系列教程2- 机器人交互实践(Topic)
  • ubuntu部署supabase