Java 8 中 ReentrantLock 与 Synchronized 的区别

news2024/11/25 12:51:32

🚀 作者主页: 有来技术
🔥 开源项目: 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.coloradmin.cn/o/1265261.html

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

相关文章

【安装指南】MySQL和Navicat下载、安装及使用详细教程

目录 ⛳️1.【MySQL】安装教程 1.1 获取下载包 1.2 MySQL安装 1.2.1 MySQL工具安装 1.2.2 MySQL环境变量 1.2.3 验证MySQL安装成功 ⛳️2.【Navicat-v15】的安装和无限使用 ⛳️3.【测试Navicat连接MySQL】 ⛳️1.【MySQL】安装教程 1.1 获取下载包 前往官网获取压缩包…

C#Backgroundworker与Thread的区别

前言 当谈到多线程编程时,C#中的BackgroundWorker和Thread是两个常见的选择。它们都可以用于实现并行处理和异步操作,但在某些方面有一些重要的区别。本文将详细解释BackgroundWorker和Thread之间的区别以及它们在不同场景中的使用。 目录 前言1. Backgr…

蓝桥杯每日一题2023.11.28

题目描述 三羊献瑞 - 蓝桥云课 (lanqiao.cn) 题目分析 本题首先进行观察可以确定 1.“三”为 1 &#xff08;十进制数字要进位进一位&#xff09; 2.“祥”一定不为 0 &#xff08;有前导0就不能算为 4 位数&#xff09; 使用搜索时将其特判 #include<bits/stdc.h> …

商用车的智慧眼车规级激光雷达

1、商用车自动驾驶技术&#xff1a;巨大的降本增效空间 2、感知是第一步&#xff1a;看懂环境路况才能安全的自动驾驶 3、多传感器融合&#xff0c;感知信息冗余&#xff0c;保障自动驾驶安全 4、商用车需要什么样的激光雷达 5、车规级激光雷达的软硬件成熟度及延展性 &#x…

Joint Bilateral Upsampling

Abstract 图像分析和增强任务&#xff08;例如色调映射、着色、立体深度和蒙太奇&#xff09;通常需要在像素网格上计算解决方案&#xff08;例如&#xff0c;曝光、色度、视差、标签&#xff09;。计算和内存成本通常要求在下采样图像上运行较小的解决方案。尽管通用上采样方…

leetcode:455. 分发饼干

一、题目 原题链接&#xff1a;455. 分发饼干 - 力扣&#xff08;LeetCode&#xff09; 函数原型&#xff1a;int findContentChildren(int* g, int gSize, int* s, int sSize) 二、思路 将胃口数组和饼干尺寸数组降序排序 遍历两个数组&#xff0c;从胃口数组中找到符合饼干尺…

【古月居《ros入门21讲》学习笔记】15_ROS中的坐标系管理系统

目录 说明&#xff1a; 1. 机器人中的坐标变换 tf功能包能干什么&#xff1f; tf坐标变换如何实现 2. 小海龟跟随实验 安装 ros-melodic-turtle-tf 实验命令 运行效果 说明&#xff1a; 1. 本系列学习笔记基于B站&#xff1a;古月居《ROS入门21讲》课程&#xff0c;且使…

Kafka事务机制:原理和实践

Kafka事务机制&#xff1a;原理和实践 Apache Kafka 是一个分布式流处理平台&#xff0c;广泛用于构建实时数据管道和流应用程序。它不仅以高吞吐量、可扩展性和容错能力著称&#xff0c;还提供了事务支持&#xff0c;以确保数据的完整性和一致性。在这篇博客中&#xff0c;我…

51单片机使用串口查看程序执行的数据

51单片机使用串口查看程序执行的数据 1.概述 这篇文章介绍利用串口输出程序执行的数据&#xff0c;辅助我们调试程序&#xff0c;提高代码定位问题的效率。 2.硬件电路原理 3.串口助手查看程序数据 输出串口数据的方式分为CPU查询方式和中断方式。他们各有优缺点&#xff0…

C语言 移位操作符

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

计网Lesson3 - 计算机网络评价指标与封包解包

文章目录 计算机网络的性能指标1. 速率2. 带宽3. 吞吐量4. 时延5. 时延带宽积6. 往返时间7. 利用率8. 数据的解包和封包 计算机网络的术语实体![实体](https://img-blog.csdnimg.cn/direct/cbf4ca9ed5ab4df290b5a17b4642c6a1.png)协议服务 计算机网络的性能指标 1. 速率 数据…

linux CentOS MobaXterm 通过X11 Forwarding 在本地开启图形可视化窗口

第一步 操作系统安装图形界面 X11 Forwarding dnf install xorg-x11-xauth xorg-x11-fonts-* xorg-x11-font-utils xorg-x11-fonts-Type1 xclock第二步 修改参数&#xff0c;启用X11 Forwarding vim /etc/ssh/sshd_config修改参数X11Forwarding yes和X11UseLocalhost no #Al…

【专题】支持向量机(Support Vector Machines,SVM)

​​​​​ ​​ 支持向量机&#xff08;Support Vector Machines&#xff0c;SVM&#xff09;是一种强大的监督学习模型&#xff0c;常用于分类、回归和异常值检测任务。它的核心思想是通过构建一个最大间隔超平面来有效地分隔不同类别的数据点。 在SVM中&#xff0c;数据点…

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

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

Linux命令进阶——grep管道命令在查看日志的场景中的使用 具体案例

前言 本篇博客介绍在查看日志的场景中&#xff0c;grep管道命令的使用&#xff0c;并给出了具体的案例。 以下为Linux相关的博客文章列表&#xff1a; Linux——认识Linux的目录结构 & 常用命令 & vim命令 & 权限及其控制 & 防火墙命令 & 自定义命令 &a…

Linux详解——常用命令(二)

目录 一、常用命令 1.进程相关命令 2.vi命令 3.软件相关命令 RPM命令 YUM命令 4.用户和组相关命令 5.权限相关命令 一、常用命令 1.进程相关命令 # 1.ps 询在当前控制台上运行的进程 ps -aux 说明:查询系统中所有运行的进程&#xff0c;包括后台进程&#xff0c;其…

【沐风老师】3DMAX拼图建模工具MaxPuzzle2D插件使用方法详解

MaxPuzzle2D拼图建模工具使用帮助 MaxPuzzle2D拼图建模工具&#xff0c;拼图建模“彩虹系列”插件&#xff0c;是一款用MAXScript脚本语言开发的3dMax拼图建模小工具&#xff0c;可以创建2D或3D的拼图图形阵列。这让需要拼图建模的设计师大大节省了时间。 MaxPuzzle2D工具界面&…

智能优化算法应用:基于头脑风暴算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于头脑风暴算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于头脑风暴算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.头脑风暴算法4.实验参数设定5.算法结果6.参考…

【技术干货】宇视IPC音频问题解决步骤

近期技术人员从宇视官网下载sdk进行二次开发时&#xff0c;在启动实时直播&#xff0c;并通过回调函数拿到流数据&#xff0c;发现没有音频流数据。 通过下面的数据发现&#xff0c;codeType此字段一直是28&#xff0c;代表的是H.264数据&#xff0c;但未没发现有音频的数据包…

CloudCompare简单开发

一、概述 CloudCompare如何进行二次开发&#xff1f;_cloudcompare 二次开发-CSDN博客 开发一个功能&#xff0c;在原始CC的基础上添加一个拓展功能&#xff0c;如下&#xff1a; 二、功能开发 1、修改MainWindow.UI 重点是&#xff1a;要编译&#xff0c;不然在mainwindow.…