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

Java | ReentrantLock 锁和 synchronized 锁的区别和共同特点是什么?

ReentrantLocksynchronized 都是 Java 中的锁机制,主要用于实现线程间的互斥访问,确保线程安全。它们有一些共同点,也有各自的特性和区别。以下是二者的详细对比:

一、共同特点

  1. 可重入性:两者都是可重入锁,即同一线程可以多次获取该锁而不会被阻塞。可重入性允许递归调用带锁的方法而不会导致死锁。

  2. 互斥性:两者都提供了互斥访问机制,确保同一时间只有一个线程能够进入受保护的代码块。

  3. 线程安全性:两者都可以保证线程安全,确保共享资源在多线程环境下不出现数据不一致的情况。

  4. 内存可见性:两者在解锁之前,都会将工作内存中的修改刷新到主内存中,这样其他线程可以看到最新的共享变量值,保证了变量在多线程环境下的可见性。

二、区别

  1. 获取锁的方式

    • ReentrantLock:可以使用 lock() 方法手动获取锁,同时提供 tryLock()lockInterruptibly() 方法,可以更灵活地控制锁的获取,例如实现带超时的锁获取,响应中断等。
    • synchronized:自动获取锁,不支持手动控制和带超时的获取,一旦进入等待状态,只能等到锁被释放或线程被中断。
  2. 锁的释放

    • ReentrantLock:需要显式调用 unlock() 方法来释放锁,通常放在 try-finally 结构中,以确保锁的正确释放。
    • synchronized:锁的释放由 JVM 自动管理,当持有锁的线程退出同步代码块时,锁会自动释放。
  3. 公平锁和非公平锁

    • ReentrantLock:可以选择公平锁(严格按照请求顺序分配)或非公平锁(可能让新来的线程插队)。通过构造函数 new ReentrantLock(true) 来创建公平锁。
    • synchronized:始终是非公平锁,不保证线程获得锁的顺序。
  4. 性能

    • ReentrantLock:在高并发环境中表现良好,非公平锁模式下性能优于 synchronized。它允许更多的控制和优化。
    • synchronized:从 Java 6 起,synchronized 得到了大量优化,如偏向锁、轻量级锁和自适应自旋锁的引入,使得 synchronized 在低竞争环境下开销更小。
  5. 中断响应

    • ReentrantLock:支持线程在等待锁时响应中断(lockInterruptibly()),适用于需要灵活控制的场景。
    • synchronized:不支持中断等待,线程在等待锁时不能响应中断。
  6. Condition条件等待

    • ReentrantLock:可以结合 Condition 实现多条件等待和唤醒,类似于 Object.wait()Object.notify(),但更加灵活。可以在一个锁上创建多个 Condition 实例,实现不同的等待队列。
    • synchronized:依赖于 wait()notify()notifyAll() 实现线程间通信,且同一对象只能有一个等待队列,控制较为简单。
  7. 灵活性

    • ReentrantLock:提供更丰富的 API 和控制手段,例如支持超时获取锁、可以查询锁状态、实现多个条件等待等,适用于复杂的并发控制场景。
    • synchronized:语法简单,适合基本的互斥需求,但灵活性较低。

三、使用建议

  • ReentrantLock 适合需要复杂锁控制的场景,如实现公平锁、响应中断、带超时的锁、多个条件等待等高并发业务逻辑。
  • synchronized 适合简单的同步操作,并且由于其简单直接和 JVM 优化,在普通的线程互斥场景中推荐使用。

总结

特性ReentrantLocksynchronized
可重入性支持支持
互斥性支持支持
锁的释放需要手动释放 (unlock())自动释放
公平锁支持不支持
性能高并发环境性能较优优化后在低并发环境性能较优
中断响应支持不支持
条件等待Condition 可实现多个条件wait()notify()notifyAll()
灵活性高,适合复杂控制低,适合基本互斥需求

选择哪种锁应基于具体业务需求。简单的同步建议使用 synchronized,而复杂的并发控制场景可以考虑 ReentrantLock


http://www.mrgr.cn/news/59944.html

相关文章:

  • 从0开始深度学习(16)——暂退法(Dropout)
  • unity中GameObject介绍
  • 如何使用Qlik Sense Util
  • (done) 什么 RPC 协议? remote procedure call 远程调用协议
  • 前端聊天室页面开发(赛博朋克科技风,内含源码)
  • 如何使用 Python 操作数据库
  • redis详细教程(2.List教程)
  • IllegalMonitorStateException:Illegal Monitor Operation 完美解决方法 ⚙️
  • Vue2 关于指令
  • 面向对象编程中类与类之间的关系(一)
  • git的学习之远程进行操作
  • 我的世界方块改进版
  • 排序算法(冒泡,插入),希尔排序(插入升级),希尔排序和插入排序时间比较!
  • JDBC: Java数据库连接的桥梁
  • ❤️算法笔记❤️-(每日一刷-5、最长回文串)
  • Kubernetes: Pod has unbound PersistentVolumeClaims
  • 土豆去皮机的结构设计(开题报告1)
  • 什么是AI神经网络?
  • 设计模式(三)
  • 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-21
  • 安装anacanda-学习笔记
  • 基于图神经网络的组合优化与推理(JML 2023)(未完)
  • linux指令笔记
  • 多线程——线程安全的集合类
  • QT 信号重载时的处理方法
  • 01.04、回文排序