什么时候用synchronized,什么时候用Reentrantlock
文章目录
- 使用 synchronized 的场景
- 使用 ReentrantLock 的场景
- 综合考虑
使用 synchronized 的场景
synchronized 是 Java 内置的同步机制,使用起来比较简单且常用于如下场景:
1、简单的同步逻辑:当你的同步逻辑非常简单,比如只需要对某个方法或代码块进行互斥访问时,synchronized 非常适用,因为它的语法简洁且易于维护。
public synchronized void simpleMethod() {// critical section
}
2、隐式监视器锁:synchronized 隐式地使用对象的监视器锁来控制同步,不需要显式的锁定和解锁操作,因此避免了锁忘记释放的问题。
3、异常安全:synchronized 块在异常发生时,会自动释放锁,确保不会因为未释放锁而导致死锁问题。
使用 ReentrantLock 的场景
ReentrantLock 是 java.util.concurrent.locks 包中提供的,更高级的锁机制,适用于以下场景:
1、需要更灵活的锁控制:ReentrantLock 提供了更多的锁控制功能,如 tryLock()(尝试锁定)和 lockInterruptibly()(可中断锁定),使得能够响应中断或超时。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class TryLockExample {private final Lock lock = new ReentrantLock();public void tryMethod() {if (lock.tryLock()) {try {// critical section} finally {lock.unlock();}} else {// handle the case where lock was not acquired}}
}
2、需要公平锁机制:ReentrantLock 支持公平锁(即先请求先获得锁),这在某些需要防止线程饥饿的场景中特别有用。
Lock fairLock = new ReentrantLock(true); // true for fairness
3、需要条件变量:ReentrantLock 提供了条件变量(Condition),可以更精细地控制线程等待和通知机制,适用于需要多个条件队列的复杂同步场景。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;// 假设我们有一个界面程序,其中一个生产者线程和两个消费者线程,
// 并且我们希望消费者1只处理奇数编号的任务,而消费者2只处理偶数编号的任务。
public class MultiConditionExample {private static final Lock lock = new ReentrantLock();private static final Condition conditionOdd = lock.newCondition();private static final Condition conditionEven = lock.newCondition();private static int count = 0;public static void main(String[] args) {Thread producer = new Thread(new Producer());Thread consumer1 = new Thread(new ConsumerOdd(), "Consumer-Odd");Thread consumer2 = new Thread(new ConsumerEven(), "Consumer-Even");producer.start();consumer1.start();consumer2.start();}static class Producer implements Runnable {@Overridepublic void run() {while (true) {try {lock.lock();count++;System.out.println("Produced: " + count);if (count % 2 == 0) {conditionEven.signal(); // Signal consumers waiting on even condition} else {conditionOdd.signal(); // Signal consumers waiting on odd condition}} finally {lock.unlock();}try {Thread.sleep(1000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}}static class ConsumerOdd implements Runnable {@Overridepublic void run() {while (true) {try {lock.lock();while (count % 2 == 0) {conditionOdd.await(); // Wait for odd number condition}// Process odd numberSystem.out.println(Thread.currentThread().getName() + " consumed: " + count);} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {lock.unlock();}}}}static class ConsumerEven implements Runnable {@Overridepublic void run() {while (true) {try {lock.lock();while (count % 2 != 0) {conditionEven.await(); // Wait for even number condition}// Process even numberSystem.out.println(Thread.currentThread().getName() + " consumed: " + count);} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {lock.unlock();}}}}
}
class MultiConditionExampleWithWaitNotify {private static final Object lock = new Object();private static int count = 0;public static void main(String[] args) {Thread producer = new Thread(new Producer());Thread consumerOdd = new Thread(new ConsumerOdd(), "Consumer-Odd");Thread consumerEven = new Thread(new ConsumerEven(), "Consumer-Even");producer.start();consumerOdd.start();consumerEven.start();}static class Producer implements Runnable {@Overridepublic void run() {while (true) {synchronized (lock) {count++;System.out.println("Produced: " + count);if (count % 2 == 0) {lock.notifyAll(); // Notify consumers waiting on even condition} else {lock.notifyAll(); // Notify consumers waiting on odd condition}}try {Thread.sleep(1000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}}static class ConsumerOdd implements Runnable {@Overridepublic void run() {while (true) {synchronized (lock) {try {while (count % 2 == 0) {lock.wait(); // Wait for odd number condition}// Process odd numberSystem.out.println(Thread.currentThread().getName() + " consumed: " + count);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}}}static class ConsumerEven implements Runnable {@Overridepublic void run() {while (true) {synchronized (lock) {try {while (count % 2 != 0) {lock.wait(); // Wait for even number condition}// Process even numberSystem.out.println(Thread.currentThread().getName() + " consumed: " + count);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}}}
}
wait 和 notify:只能使用单一的监视器锁,并通过 notify 或 notifyAll 来通知等待线程。由于所有线程都在同一个锁对象上等待,即使只需要唤醒部分线程(例如只唤醒等待奇数的线程),也必须通知所有等待的线程(使用 notifyAll),这样会导致非目标线程频繁被唤醒和再次等待。
Condition:可以创建多个 Condition 实例,在不同的条件队列上管理等待和通知。只会唤醒指定条件下的线程,从而提高效率。
综合考虑
简洁性和安全性:如果你的同步需求简单,且不需要复杂的锁定逻辑,选择 synchronized 更为简洁和安全。
灵活性和功能:如果需要更灵活的锁控制、更高的性能、更多的特性(如条件变量、尝试锁定、响应中断等),ReentrantLock 提供更强大的功能。
相关文章:
什么时候用synchronized,什么时候用Reentrantlock
文章目录 使用 synchronized 的场景使用 ReentrantLock 的场景综合考虑 使用 synchronized 的场景 synchronized 是 Java 内置的同步机制,使用起来比较简单且常用于如下场景: 1、简单的同步逻辑:当你的同步逻辑非常简单,比如只需…...
[ffmpeg]音频格式转换
本文主要梳理 ffmpeg 中的音频格式转换。由于采集的音频数据和编码器支持的音频格式可能不一样,所以经常需要进行格式转换。 API 调用 常用 API struct SwrContext *swr_alloc(void); int swr_init(struct SwrContext *s); struct SwrContext *swr_alloc_set_opt…...
SSRF工具类-SsrfTool
为了帮助开发人员和安全研究人员检测和修复SSRF(Server-Side Request Forgery)漏洞,存在 多种工具。这里我将给出一个简单的工具类示例,这个工具类可以用来检查一个给定的URL是否可 能引发SSRF攻击。请注意,这个工具类主要用于教育目的,并不意味着它可以完全防止所有的…...
python集合运算介绍及示例代码
Python 中的集合(set)是一种数据类型,用于存储唯一元素的无序集合。集合支持多种运算,如并集、交集、差集和对称差集,方便执行数学上的集合操作。 1. 创建集合 可以使用大括号 {} 或者 set() 函数创建集合࿱…...
『功能项目』按钮的打开关闭功能【73】
本章项目成果展示 我们打开上一篇72QFrameWork制作背包界面UGUI的项目, 本章要做的事情是制作打开背包与修改器的打开关闭按钮 首先打开UGUICanvas复制button按钮 重命名为ReviseBtn 修改脚本:UIManager.cs 将修改器UI在UGUICanvas预制体中设置为隐藏 运…...
Linux 常用命令 - more 【分页显示文件内容】
简介 more 命令源自英文单词 more, 表示 “更多”,它是一个基于文本的程序,用于查看文本文件的内容。该命令会逐页显示文件内容,允许用户按页浏览大型文本文件。当用户完成当前页的阅读后,可以通过按键(空格键或回车键…...
Kotlin Android 环境搭建
Kotlin Android 环境搭建 1. 引言 Kotlin 已成为 Android 开发的官方语言之一,因其简洁、表达性强和易于维护的特点而受到广大开发者的喜爱。在本教程中,我们将详细介绍如何在您的计算机上搭建 Kotlin Android 开发环境。 2. 系统要求 在开始搭建 Kotlin Android 开发环境…...
常见协议及其默认使用的端口号
在网络通信中,端口号用于标识特定的应用程序或服务。IANA(Internet Assigned Numbers Authority)负责分配和管理这些端口号。端口号分为三个范围: 熟知端口(Well-Known Ports):0到1023…...
04-Docker常用命令
04-Docker常用命令 启动类命令 启动docker systemctl start docker停止docker systemctl stop docker重启docker systemctl restart docker查看docker状态 systemctl status docker开机启动docker systemctl enable docker帮助类命令 查看docker版本 docker version查…...
数字化转型中的供应链管理优化
在当今全球化和数字化的浪潮下,企业供应链管理面临着前所未有的挑战和机遇,企业在数字化转型过程中,如何优化供应链管理成为提升竞争力的关键。通过应用先进技术如RPA机器人流程自动化、大数据分析、物联网等,企业可以显著提高物流…...
【Python报错已解决】SyntaxError: invalid syntax
🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 专栏介绍 在软件开发和日常使用中,BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…...
树上差分+lca 黑暗的锁链
//** 太久不写了,感觉很难受。。。比赛最近打得也不好,课内任务又重,还要忙着做项目。何去何从。 今天又写了一题,用了树上差分的知识。下面来整理整理。 1.首先让我们学一下lca(最小公共父节点) 我用的…...
opencv4.5.5 GPU版本编译
一、安装环境 1、opencv4.5.5 下载地址:https://github.com/opencv/opencv/archive/refs/tags/4.5.5.ziphttps://gitee.com/mirrors/opencv/tree/4.5.0 2、opencv-contrib4.5.5 下载地址:https://github.com/opencv/opencv_contrib/archive/refs/tags/4…...
线性跟踪微分器TD详细测试(Simulink 算法框图+SCL完整源代码)
1、ADRC线性跟踪微分器 ADRC线性跟踪微分器(ST+SCL语言)_adrc算法在博途编程中scl语言-CSDN博客文章浏览阅读784次。本文介绍了ADRC线性跟踪微分器的算法和源代码,包括在SMART PLC和H5U平台上的实现。文章提供了ST和SCL语言的详细代码,并讨论了跟踪微分器在自动控制中的作用…...
LabVIEW闪退
LabVIEW闪退或无法启动可能由多个原因引起,特别是在使用了一段时间后突然发生的问题。重启电脑后 LabVIEW 和所有 NI 软件都无法打开,甚至在卸载和重装时也没有反应。这种情况通常与系统环境、软件冲突或 NI 软件组件的损坏有关。 1. 检查系统和软件冲突…...
【WPF】03 动态生成控件
说明 今天记录一篇关于动态生成控件的方法,也是反复查了一些资料,逐步完善成自己需要的方法,感觉还是比较好用的。通过这个需求,在网上也找了一些资料,发现了一个开源图形UI组件HandyControl,觉得比较好&a…...
调试LTE模块碰到的4字节对齐问题
在调试LTE模块,有两个模块,碰到两种4字节对齐问题,其错误提示都是类似如下的内容: DWC_OTG: dwc_otg_hcd_urb_enqueue urb->transfer_buffer address not align to 4-byte 0xee419e8e 都是USB控制器处理的数据时需要4字节对齐…...
一篇讲完HTML核心内容
一、HTML 1、 HTML概念 网页,是网站中的一个页面,通常是网页是构成网站的基本元素,是承载各种网站应用的平台。通俗的说,网站就是由网页组成的。通常我们看到的网页都是以htm或html后缀结尾的文件,俗称 HTML文件。 2、…...
2024icpc(Ⅱ)网络赛补题 G
2024icpc(Ⅱ)网络赛补题 G 题目链接:The 2024 ICPC Asia EC Regionals Online Contest (II) G、Game 题意: 给定Alice和Bob的每一轮的概率 p 0 , p 1 p_0, p_1 p0,p1 给定Alice和Bob的初始数字 x , y x,y x,y。 对于每一轮: 如果Al…...
AIGC时代!AI的“iPhone时刻”与投资机遇
AIGC时代!AI的“iPhone时刻”与投资机遇 前言AI的“iPhone时刻”与投资机遇 前言 AIGC,也就是人工智能生成内容,它就像是一股汹涌的浪潮,席卷了整个科技世界。它的出现,让我们看到了人工智能的无限潜力,也…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
python打卡第47天
昨天代码中注意力热图的部分顺移至今天 知识点回顾: 热力图 作业:对比不同卷积层热图可视化的结果 def visualize_attention_map(model, test_loader, device, class_names, num_samples3):"""可视化模型的注意力热力图,展示模…...
Qt的学习(二)
1. 创建Hello Word 两种方式,实现helloworld: 1.通过图形化的方式,在界面上创建出一个控件,显示helloworld 2.通过纯代码的方式,通过编写代码,在界面上创建控件, 显示hello world; …...
自定义线程池1.2
自定义线程池 1.2 1. 简介 上次我们实现了 1.1 版本,将线程池中的线程数量交给使用者决定,并且将线程的创建延迟到任务提交的时候,在本文中我们将对这个版本进行如下的优化: 在新建线程时交给线程一个任务。让线程在某种情况下…...
