Java 8 中 ReentrantLock 与 Synchronized 的区别

🚀 作者主页: 有来技术
🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot
🌺 仓库主页: Gitee 💫 Github 💫 GitCode
💖 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请纠正!

目录

  • 引言
  • 同步机制简介
    • Synchronized
    • ReentrantLock
  • 区别分析
    • 可中断性
    • 公平性
    • 条件变量
    • 性能比较
  • Java 8 的新特性
  • 面试题解析
    • 什么时候使用 ReentrantLock 而不是 synchronized?
    • ReentrantLock 的可重入性是什么意思?
    • 什么是乐观读锁?StampedLock 有什么优势?
  • 总结

引言

在Java多线程编程中,确保线程安全是至关重要的。为了实现线程的同步和协作,Java提供了多种同步机制,其中最常见的是使用 synchronized 关键字和 ReentrantLock 类。这两者在实现线程安全的同时,也存在着一些区别。本文将深入讨论这两种同步机制的差异,并结合 Java 8 的特性,解析它们在常见面试题中的应用。

同步机制简介

Synchronized

在这里插入图片描述

synchronized 是Java中最早引入的同步机制,通过对方法或代码块加锁来确保多线程环境下的数据一致性。它使用起来简单,不需要手动释放锁,JVM会自动管理。

public synchronized void synchronizedMethod() {// 同步代码块// ...
}

ReentrantLock

ReentrantLock 是Java 5 中引入的同步机制,相较于 synchronized,它提供了更灵活的锁定方式。通过显式地获取锁和释放锁,程序员可以更精细地控制同步操作。此外,ReentrantLock 还支持可重入性,即一个线程可以多次获取同一个锁。

import java.util.concurrent.locks.ReentrantLock;public class MyLock {private final ReentrantLock lock = new ReentrantLock();public void lockedMethod() {lock.lock();try {// 同步代码块// ...} finally {lock.unlock();}}
}

区别分析

可中断性

一个显著的区别是 ReentrantLock 支持中断等待锁的线程,而 synchronized 不支持。在 ReentrantLock 中,线程可以通过 lockInterruptibly 方法等待锁,如果其他线程中断了当前线程,它可以响应中断而不是一直等待。

ReentrantLock lock = new ReentrantLock();public void interruptibleMethod() throws InterruptedException {lock.lockInterruptibly();try {// 同步代码块// ...} finally {lock.unlock();}
}

公平性

ReentrantLock 可以选择是否公平地获取锁,而 synchronized 是非公平的。在公平模式下,等待时间最长的线程会优先获得锁。在非公平模式下,线程有一定几率在等待队列为空时插队成功。

ReentrantLock fairLock = new ReentrantLock(true); // 公平锁
ReentrantLock unfairLock = new ReentrantLock();     // 非公平锁

条件变量

ReentrantLock 提供了 Condition 接口,可以通过 newCondition 方法创建多个条件变量,用于在不同的情况下等待或唤醒线程。而 synchronized 只能通过 ObjectwaitnotifynotifyAll 方法来实现简单的线程协作,缺乏 ReentrantLock 中的灵活性。

ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();public void awaitSignal() throws InterruptedException {lock.lock();try {condition.await();} finally {lock.unlock();}
}public void sendSignal() {lock.lock();try {condition.signal();} finally {lock.unlock();}
}

性能比较

在 Java 5 之前,synchronized 的性能较差,但在 Java 6 及以后的版本中,对 synchronized 进行了优化,性能已经有了很大的提升。一般来说,在性能上,synchronizedReentrantLock 的差距并不明显。在选择使用时,更应该考虑到代码的可读性和维护性。

Java 8 的新特性

Java 8 引入了函数式编程的特性,同时也对并发编程做出了一些改进。其中一个显著的改变是引入了新的 StampedLock 类,它是 ReentrantLock 的进一步扩展,提供了乐观锁机制,使得在读多写少的场景下性能更优。

import java.util.concurrent.locks.StampedLock;public class MyStampedLock {private final StampedLock lock = new StampedLock();public void read() {long stamp = lock.tryOptimisticRead();// 乐观读操作if (!lock.validate(stamp)) {// 如果发生了写操作,则使用悲观读锁stamp = lock.readLock();try {// 悲观读操作} finally {lock.unlockRead(stamp);}}}public void write() {long stamp = lock.writeLock();try {// 写操作} finally {lock.unlockWrite(stamp);}}
}

面试题解析

什么时候使用 ReentrantLock 而不是 synchronized?

  • 需要支持可中断等待: 如果你的线程需要响应中断而不是一直等待锁,那么 ReentrantLock 是更好的选择。
  • 需要尝试获取锁: ReentrantLock 提供了 tryLock 方法,可以尝试获取锁而不一直等待,可以用于避免死锁。
  • 需要选择公平性: 如果你需要控制线程获取锁的顺序,可以选择 ReentrantLock 的公平锁或非公平锁。

ReentrantLock 的可重入性是什么意思?

可重入性是指同一个线程在持有锁的情况下,能够再次获取这个锁而不发生死锁。ReentrantLocksynchronized 都是可重入的,这使得线程可以递归地调用同步方法或同步代码块。

什么是乐观读锁?StampedLock 有什么优势?

乐观读锁是 StampedLock 引入的特性,它允许多个线程同时读取共享资源,而不会阻塞写锁。如果在乐观读锁期间没有写锁被获取,读操作可以立即进行。当然,如果写锁被获取,就需要转为悲观读锁。

StampedLock 的优势在于在读多写少的场景下性能更优,因为它允许多个线程同时读取,而不阻塞彼此。

总结

在Java 8中,ReentrantLocksynchronized 依然是同步机制中的主流选择。选择使用哪一种取决于具体的需求和场景。总体而言,synchronized 在简单场景下易用性更高,而 ReentrantLock 则在一些复杂场景下提供了更多的灵活性和控制权。

对于面试而言,了解这两者的区别、使用场景以及新特性,可以展现出对多线程编程深入理解的能力,为应对面试中的技术问题提供有力支持。在实际应用中,结合业务需求和性能要求,选择适当的同步机制是至关重要的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/180205.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《微信小程序开发从入门到实战》学习三十五

4.2 云开发JSON数据库 4.2.3 权限控制 在云开发控制台可以对数据库中的数据进行操作, 在小程序端和云函数可以分别使用小程序API和服务端API对数据中的数据进行操作。 以上操作受到权限控制。 对数据库进行查询属于读操作,增删改操作属于写操作。 …

Day44力扣打卡

打卡记录 给小朋友们分糖果 II(容斥原理 隔板法) 链接 def c2(n):return n * (n - 1) // 2 if n > 1 else 0class Solution:def distributeCandies(self, n: int, limit: int) -> int:return c2(n 2) - 3 * c2(n - limit 1) 3 * c2(n - 2 * …

Python实现byte数或者整数的循环位移

文章目录 1 Introduction2 Code2.1 Output2.2 复杂度分析 参考资料 Bit Rotation: A rotation (or circular shift) is an operation similar to a shift except that the bits that fall off at one end are put back to the other end. In the left rotation, the bits that …

结构体训练

1. 评委打分 【问题描述】 校园卡拉OK比赛设置了7名评委,当一名选手K完歌之后,主持人报出歌手名字后,7位评委同时亮分,按照惯例,去掉一个最高分和一个最低分后,其余5位评委评分总和为该选手的最终得分。 一…

uniapp+微信小程序监听返回事件

代码附在最后 适用场景:uniapp开发微信小程序 需求是我点击列表进入数据信息的详情界面,点击详情界面的收藏,返回上一界面后,更新列表中的收藏情况。 目录 一、使用onUnload监听页面卸载 二、使用getCurrentPages()获取当前页…

【双指针】四数之和

四数之和 建议做过了解三数之和的思想再做这道题,思路是一样的~ 题目描述 18. 四数之和 - 力扣(LeetCode) 给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [num…

搞定ESD(六):静电放电问题典型案例分析(一)

文章目录 一、接触放电测试出现系统自动待机问题案例分析(一)1. 问题现象描述2. 问题现象分析3. 问题分析验证过程3.1 MCU芯片供电电源稳定性分析验证3.2 MCU芯片复位电路稳定性验证4. 问题分析产生原因分析5. 问题解决方案6. 案例总结二、接触放电测试出现系统自动待机问题案…

Java大型智慧工地APP云平台源码带AI智能识别功能

智慧工地为建筑全生命周期赋能,用创新的可视化与智能化方法,降低成本,创造价值。 一、智慧工地APP概述 智慧工地”立足于互联网,采用云计算,大数据和物联网等技术手段,针对当前建筑行业的特点,…

让KVM支持滚动热升级:Multi-KVM

Multi-KVM 允许多个独立的 KVM 模块在同一台 Linux 主机上同时加载、卸载和运行。主要包括: 升级和回滚 KVM,而不会中断正在运行的虚拟机 允许在同一主机上运行具有不同参数的 KVM 模块 为 KVM 的 A/B 测试提供便利 1. 设计方案 隔离性 从整个内核中…

C语言 移位操作符

<< 左移操作符>> 右移操作符 注&#xff1a;移位操作符的操作数只能是整数。 移位操作符移动的是二进制位。 整数的二进制表示有3种&#xff1a; 原码反码补码 正的整数的原码、反码、补码相同。 负的整数的原码、反码、补码是要计算的。 由负整数原码计算出反…

编写安全 JavaScript 代码的最佳实践

编写安全 JavaScript 代码的最佳实践 JavaScript 的动态特性使其成为事实上的浏览器语言和世界上最流行的编程语言。 JS 最受欢迎的有用功能之一是即时分析。这意味着浏览器在下载内容的同时执行代码&#xff0c;这显然有其优势。然而&#xff0c;这种程度的自由也伴随着问题…

广域网技术

广域网 wide area net(WAN) 电路交换网分组交换网&#xff08;数据报|虚电路&#xff09;专用线路网 静态路由算法: 手动填入路径至路由表中,且路径保持不变. 适用于拓扑结构比较稳定, 网络规模比较小的网络。 动态路由算法 通过与邻居通信 不断学习, 根据网络拓扑结构变化而…

【工业智能】Solutions

各类问题对应的解决方案 工艺参数推荐APC 排产调度智能算法强化学习 运筹优化空压机群控 预测 工艺参数推荐 APC 排产调度 智能算法 遗传算法 强化学习 DDQN 运筹优化 空压机群控 MIP混合整数规划 能耗优化 预测 电池容量预测 时序预测&#xff0c;回归预测 点击剩余…

【好用的个人工具】在Docker环境下部署Simple mind map思维导图工具

【好用的个人工具】在Docker环境下部署Simple mind map思维导图工具 一、Simple mind map介绍1.1 Simple mind map简介1.2 Simple mind map特点 二、本地环境介绍2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker co…

Java后端使用XWPFDocument生成word文档,踩坑

以下都是借鉴网上内容: 环境 纯后端, java, spring项目 maven管理. maven内容: <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.16</version></dependency><dependency>…

Centos查看运行内存大小

在CentOS上&#xff0c;你可以使用以下几种方法来查看内存占用情况&#xff1a; 使用 free 命令&#xff1a; free -h这个命令会显示系统的物理内存和交换空间使用情况&#xff0c;以人类可读的方式显示。 使用 top 命令&#xff1a; top在top命令的输出中&#xff0c;第一…

Django:通过user-agent判断请求是来自移动端还是PC端(电脑端)

第一种思路&#xff1a; 根据博文 Djano的request.META是什么&#xff1f;的研究成果&#xff0c;先判断有无键HTTP_SEC_CH_UA_MOBILE&#xff0c;如果没有&#xff0c;再去按博文 网站如何判断请求是来自手机-移动端还是PC-电脑端&#xff1f;如何让网站能适应不同的客户端&am…

Flink流批一体计算(21):Flink SQL之Flink DDL

目录 执行 CREATE 语句 Python脚本 Java代码 SQL语句 列定义 物理/常规列 元数据列 计算列 WATERMARK PRIMARY KEY PARTITIONED BY AS select_statement Flink SQL是为了简化计算模型、降低您使用Flink门槛而设计的一套符合标准SQL语义的开发语言。 执行 CREATE 语…

freerots启动过程分析(qemu仿真RISC-V架构为例)

1、前言 本文是基于qemu上virt板子适配的freertos系统源码进行讲解qemu安装可参考博客&#xff1a;《qemu源码下载和安装》&#xff1b;freertos移植到qemu上运行可参考博客&#xff1a;《移植freertos到qemu上运行》&#xff1b; 2、汇编代码部分 汇编文件&#xff1a;FreeR…

集成学习的两种常见策略:bagging VS. boosting

chatGPT回答&#xff0c;记在这里。 集成学习是一种通过组合多个弱学习器来构建一个更强大的学习器的方法。其中&#xff0c;bagging和boosting是两种常见的集成学习策略。 一、bagging & boosting 简介 Bagging&#xff08;自助聚集法&#xff09;&#xff1a; Bagging…