什么时候用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,也就是人工智能生成内容,它就像是一股汹涌的浪潮,席卷了整个科技世界。它的出现,让我们看到了人工智能的无限潜力,也…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...

自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...