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

news/2024/10/28 21:32:40/

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.ppmy.cn/news/1542692.html

相关文章

深度学习速通系列:超长法律文件隐私过滤(基于预训练模型Bert)

法律文件隐私过滤 网上使用bert的中文模型进行命名识别教程少的可怜,摸索了一周的时间,硬是把法律文书的人名全部识别出来了,目前可以达到98.9999%(开玩笑的,不过准确率保守估计是有90%以上).注意:这个法律文书目前只是针对裁决书,其他还没测试过,可支持超长文本识别 github仓…

小米面试题:多级缓存一致性问题怎么解决

前言 在现代分布式系统中,多级缓存架构因其能够显著提高系统性能和响应速度而被广泛应用。然而,多级缓存架构也带来了一致性问题,即不同层次的缓存之间数据不一致的情况。本文将从背景、功能点、优缺点、底层原理等方面详细介绍多级缓存一致…

Nodejs使用pkg打包为可执行文件

安装pkg npm install -g pkg查看pkg命令 pkg --help修改package.json 新增bin入口配置 {"name": "takescreenshot","version": "1.0.0","bin": "app.js", // 新增bin入口配置"scripts": {"t…

GPU 与 GPU 服务器:科技璀璨之星,开启无限未来

今天咱们要来聊聊在科技领域中闪闪发光的 GPU 和 GPU 服务器。这可真是一对厉害的 “科技搭档”,正以其卓越的性能成为众多行业发展的强大动力源。 先来说说 GPU 吧。它呀,一开始是为了满足图形处理的高要求而诞生的。但随着科技不断进步,人…

C语言串口接收GPS数据

要在C语言中接收GPS数据,需要使用串口通信来与GPS设备进行数据交互。一个简单的串口通信代码主要包含了以下几个部分: 1.标准库头文件 stdio.h:包含输入输出函数,如 printf string.h:包含字符串处理函数&#xff0c…

Django-中间件(切面编程AOP)

自定义中间件 官网:中间件 | Django 文档 | Django 中间件使用多就在主应用创建,仅限于子应用就在子引用中创建中间件文件.py 之后在settings.py文件中去配置中间件,运行的时候会自动调用中间件 def simple_middleware(get_response):def middleware…

在 .NET 8 Web API 中实现 Entity Framework 的 Code First 方法

本次介绍分为3篇文章: 1:.Net 8 Web API CRUD 操作.Net 8 Web API CRUD 操作-CSDN博客 2:在 .Net 8 API 中实现 Entity Framework 的 Code First 方法https://blog.csdn.net/hefeng_aspnet/article/details/143229912 3:.NET …

rtp协议:rtcp包格式和传输间隔

RTP Control Protocol -- RTCP-rtp控制协议 实时传输控制协议(RTCP)基于对会话中的所有参与者定期传输控制包,使用与数据包相同的分发机制。底层协议必须提供数据包和控制包的多路复用,例如使用UDP时使用不同的端口号。RTCP执行四…