Spring 代理与 Redis 分布式锁冲突:一次锁释放异常的分析与解决
Spring 代理与 Redis 分布式锁冲突:一次锁释放异常的分析与解决
- Spring 代理与 Redis 分布式锁冲突:一次锁释放异常的分析与解决
- 1. 问题现象与初步分析
- 2 . 原因探究:代理机制对分布式锁生命周期的干扰
- 3. 问题复现伪代码
- 4. 解决方案:构建健壮的分布式锁集成
- 核心原则:
- 实施要点:
- 5. 技术沉淀与反思
- 6. 技术方案对比
- 7.问题总结
Spring 代理与 Redis 分布式锁冲突:一次锁释放异常的分析与解决
1. 问题现象与初步分析
系统告警或用户反馈偶发性操作失败,具体表现为涉及并发访问的业务功能(如订单创建、库存扣减)返回错误。通过日志系统排查,发现关键异常堆栈如下:
异常信息明确指示当前线程尝试释放一个非其持有的锁。结合堆栈信息中 org.springframework.cglib.proxy 和 org.springframework.aop.framework.CglibAopProxy
的存在,初步判断问题与 Spring 的代理机制(通过 CGLIB 实现)对目标方法的拦截处理紧密相关。同时,考虑到业务场景使用了 Redis 分布式锁,推测是代理机制与分布式锁的获取/释放逻辑在并发环境下产生了冲突。
2 . 原因探究:代理机制对分布式锁生命周期的干扰
“attempt to unlock lock, not locked by current thread
”异常的本质是分布式锁的持有者与尝试释放者身份不匹配。在基于 Redis 的分布式锁实现中,通常使用一个与请求或线程相关的唯一标识符(value)来标记锁的持有权。安全的锁释放操作必须验证 Redis 中存储的 value 与尝试释放者的标识符是否一致。
结合 Spring 代理特性,深入分析问题产生的可能原因:
- 代理逻辑对业务层方法执行流程的改变: Spring AOP 或事务代理通过在目标方法调用前后织入额外的逻辑。当业务层方法被代理时,实际执行路径是 调用方 -> 代理对象 -> 代理逻辑(前置) -> 目标对象方法 -> 代理逻辑(后置/异常处理)。如果在目标方法内部获取了分布式锁,而代理层在后置处理(如事务提交/回滚)或异常处理过程中,以某种方式影响了线程上下文或锁释放逻辑的执行时机,就可能导致问题。
- 异常处理路径下的锁释放问题:
业务层方法中的异常会被 Spring 代理捕获并触发相应的处理(如事务回滚)。如果在 try-catch-finally 结构中,锁释放逻辑位于 finally 块,当异常发生时,代理层的异常处理可能在 finally 块执行之前或之中介入。这可能导致 finally 块在非预期的线程上下文执行,或者代理层的某些清理逻辑(错误地)尝试释放锁。 - 锁过期与业务执行时长:
Redis 分布式锁通常设置有过期时间(TTL)。如果业务层方法的执行时间超过了锁的 TTL,Redis 会自动释放锁。此时,其他线程可能获取到新的锁。当原先持有锁的线程(经过长时间业务处理和代理逻辑后)最终到达 finally 块尝试释放锁时,它面对的 Redis Key 可能已经被其他线程持有,导致释放失败并抛出异常(取决于你的分布式锁客户端实现是否会抛出此类异常)。
- 分布式锁释放的非原子性: 如果分布式锁的释放逻辑不是原子操作(例如,先 GET key 检查 value,再 DEL key),在检查和删除之间存在时间窗口。在这个窗口内,锁可能被其他线程获取并修改了 value。后续的 DEL 操作就会错误地删除了其他线程的锁。虽然这直接导致的是锁被误删,但在某些客户端实现中,这种非持有者尝试操作锁的行为也可能被检测并报告为类似“锁不属于当前线程”的问题。
3. 问题复现伪代码
以下伪代码模拟在被 Spring 代理的业务层方法中,使用 Redis 分布式锁并可能导致冲突的场景:
// 模拟 Redis 分布式锁客户端(简化版)
public class SimplifiedRedisLockClient { // 假设 Redis 有 SET key value NX PX expireTime 命令 // 成功返回 true,失败返回 false public boolean acquireLock(String key, String value, long expireTime) { // 模拟调用 Redis SET 命令 System.out.println(Thread.currentThread().getName() \+ " \- Attempting to acquire lock for key: " \+ key \+ " with value: " \+ value); // 实际应与 Redis 交互,此处简化为模拟成功 return true; }// 模拟释放锁,需要检查 value 是否匹配,并保证原子性(虽然伪代码无法完全模拟原子性) public boolean releaseLock(String key, String value) { // 模拟调用 Redis Lua 脚本: // IF redis.call("GET", KEYS\[1\]) \== ARGV\[1\] THEN return redis.call("DEL", KEYS\[1\]) ELSE return 0 END System.out.println(Thread.currentThread().getName() \+ " \- Attempting to release lock for key: " \+ key \+ " with value: " \+ value);// 模拟检查 value 不匹配(例如锁已过期被其他线程获取),返回 false // 实际应与 Redis 交互并执行 Lua 脚本 boolean isOwner \= checkLockOwnership(key, value); // 模拟检查是否是持有者 if (isOwner) { // 模拟删除 key System.out.println(Thread.currentThread().getName() \+ " \- Owner matched, simulating DEL key: " \+ key); return true; // 模拟释放成功 } else { System.out.println(Thread.currentThread().getName() \+ " \- Owner mismatch or lock expired for key: " \+ key); return false; // 模拟释放失败 } }// 模拟检查锁所有权(非原子,仅用于伪代码演示概念) private boolean checkLockOwnership(String key, String value) { // 在实际分布式系统中,这里的 GET 和 DEL 必须是原子的,通过 Lua 脚本实现 // 模拟一个场景:锁已过期或被其他线程获取 // 例如,可以基于一个共享的 Map 来模拟 Redis 状态,但在并发下 Map 操作本身也需同步 return false; // 简化演示:模拟检查发现不是持有者 }
}// 业务服务接口
public interface MyBusinessService { void performCriticalBusinessOperation(String data);
}// 业务服务实现类,被 Spring 代理 (如 @Transactional)
@Service // 标记为 Spring Service 组件
public class MyBusinessServiceImpl implements MyBusinessService {private final SimplifiedRedisLockClient redisLockClient; private final String lockKey \= "my\_business\_resource\_lock"; // 锁定的资源 Keypublic MyBusinessServiceImpl(SimplifiedRedisLockClient redisLockClient) { this.redisLockClient \= redisLockClient; }@Override @Transactional // 业务层方法,通常带有事务注解,会被 Spring 代理 public void performCriticalBusinessOperation(String data) { // 生成一个与当前请求/线程相关的唯一标识符 String lockValue \= Thread.currentThread().getId() \+ "\_" \+ UUID.randomUUID().toString(); boolean lockAcquired \= false;// Spring 代理逻辑开始 (如事务开启)try { // 在业务方法内部尝试获取分布式锁 // 锁过期时间设置为 5 秒 lockAcquired \= redisLockClient.acquireLock(lockKey, lockValue, 5000);if (lockAcquired) { // 核心业务逻辑:只有获取锁的线程才能执行 System.out.println(Thread.currentThread().getName() \+ " \- Acquired distributed lock, executing business logic for: " \+ data);// 模拟业务耗时,可能超过锁的过期时间 Thread.sleep(6000); // 模拟耗时 6 秒,大于锁的 5 秒过期时间// 模拟业务逻辑中的异常情况 if (data.contains("error")) { System.out.println(Thread.currentThread().getName() \+ " \- Business logic encountered error."); throw new RuntimeException("Simulated business logic error"); }System.out.println(Thread.currentThread().getName() \+ " \- Business logic completed successfully.");} else { System.out.println(Thread.currentThread().getName() \+ " \- Failed to acquire distributed lock for business operation. Resource is busy."); // 处理未能获取锁的情况,例如抛出业务异常或返回特定错误码 // throw new BusinessBusyException("Resource is currently locked."); }} catch (InterruptedException e) { Thread.currentThread().interrupt(); System.out.println(Thread.currentThread().getName() \+ " \- Business operation interrupted."); // 异常处理 } catch (RuntimeException e) { System.out.println(Thread.currentThread().getName() \+ " \- Caught RuntimeException: " \+ e.getMessage()); throw e; // 重新抛出异常,触发 Spring 事务回滚和代理的异常处理 } finally { // 在 finally 块中尝试释放锁 // 问题在于,如果 Spring 代理在异常处理或事务回滚时介入, // 可能导致在此处执行释放逻辑的线程上下文与获取锁时不同, // 或者锁已过期被其他线程持有(如上面的模拟耗时超过过期时间) if (lockAcquired) { System.out.println(Thread.currentThread().getName() \+ " \- Entering finally block to release lock."); // 模拟调用释放锁,可能因为非持有者或锁已过期而失败 boolean released \= redisLockClient.releaseLock(lockKey, lockValue); if (\!released) { System.out.println(Thread.currentThread().getName() \+ " \- Failed to release lock: Not held by current thread or already expired."); // 在实际场景中,这里的失败可能导致日志中的 "attempt to unlock lock, not locked by current thread" 异常 // 具体取决于你的分布式锁客户端实现 } else { System.out.println(Thread.currentThread().getName() \+ " \- Successfully released lock."); } } // Spring 代理逻辑结束 (如事务提交/回滚) System.out.println(Thread.currentThread().getName() \+ " \- Exiting business method."); } }
}// 在控制器或其他调用方,通过 Spring 注入的代理对象并发调用业务方法
// 例如:
// @Autowired
// private MyBusinessService myBusinessServiceProxy; // Spring 注入的是代理对象
//
// // 在多个线程中执行并发调用
// ExecutorService executorService \= Executors.newFixedThreadPool(10);
// executorService.submit(() \-\> myBusinessServiceProxy.performCriticalBusinessOperation("data1"));
// executorService.submit(() \-\> myBusinessServiceProxy.performCriticalBusinessOperation("data2"));
// ...
// executorService.shutdown();
4. 解决方案:构建健壮的分布式锁集成
核心原则:
- 确保 Redis 分布式锁的获取和释放逻辑在复杂的分布式环境和 Spring 代理机制下依然安全、原子化,并正确管理锁的生命周期。
实施要点:
- 安全的锁释放(强制要求): 必须使用 Lua 脚本保证锁释放的原子性。Lua 脚本能在 Redis 服务器端一次性完成“检查 value 是否匹配”和“删除 key”两个操作,避免竞态条件。这是防止误删其他线程锁的关键。
- . 正确处理锁过期与续期:
- 评估核心业务逻辑的最大执行时间,合理设置锁的过期时间。
- 对于可能长时间运行的业务逻辑,强烈建议实现锁续期机制(Watchdog)。在锁即将过期前,自动向 Redis 发送续期命令,延长锁的持有时间,直到业务完成。常用的分布式锁库(如 Redisson)通常内置了 Watchdog 机制。
- 将锁操作封装到独立组件或使用成熟库: 避免在业务方法内部直接编写 Redis 锁操作代码。将分布式锁的获取、续期、释放逻辑封装到一个独立的工具类或服务中。更好的实践是使用经过广泛验证的分布式锁库(如 Redisson、Lettuce 的分布式锁实现),它们通常已经处理好了原子性、续期、重试等复杂问题。
- 谨慎处理业务异常对锁释放的影响: 确保在业务层方法的异常处理路径中,锁释放逻辑能够被正确触发和执行。将锁释放放在 finally 块是标准做法,但需要结合 Spring 代理的异常处理机制进行验证。使用成熟的分布式锁库可以简化这部分处理,因为库本身会负责在锁持有者线程终止时尝试释放锁。
- 隔离事务与锁逻辑(可选但推荐): 如果可能,考虑将获取/释放分布式锁的逻辑与核心业务事务逻辑适度分离。例如,在获取锁后,再开启数据库事务执行业务操作。这样可以减少事务回滚对锁状态的影响。
5. 技术沉淀与反思
- 分布式系统复杂性: 分布式环境下的并发控制远比单体应用复杂,需要全面考虑网络通信、节点状态、时钟同步等因素。
- 框架与中间件的交互: 深入理解 Spring 代理、事务管理器等框架组件与 Redis、消息队列等中间件的交互机制,尤其是在异常和并发场景下。
- 分布式锁的挑战与最佳实践: 认识到简单的 SET NX + DEL 并非安全的分布式锁,必须掌握原子性释放(Lua 脚本)和锁续期等核心概念。
- 故障模式思考: 在设计并发系统时,需要主动思考各种潜在的故障模式(网络分区、节点宕机、业务异常)以及它们对锁状态的影响。
- 选择合适的工具: 优先使用经过社区广泛验证的分布式锁库,而非自己实现,以规避潜在的 Bug。
6. 技术方案对比
- 优化 Redis 分布式锁实现及与业务层方法的集成(采用): 专注于提升分布式锁本身的健壮性(原子释放、续期),并确保其在 Spring 代理环境下能正确工作。这是解决根本问题的最有效途径。
- 优点: 治本,提高系统在分布式并发场景下的稳定性。
- 缺点: 需要对分布式锁原理有较深入理解,可能需要引入第三方库。
- 调整 Spring 代理配置: 尝试修改 Spring AOP/事务配置以避免与锁逻辑冲突。
- 优点: 可能无需改动业务逻辑。
- 缺点: 可行性低,依赖于对 Spring 内部机制的深入了解,不易维护,且可能无法从根本上解决锁过期等问题。
- 使用其他分布式锁方案: 考虑基于 ZooKeeper 或数据库的分布式锁。
- 优点: 提供不同的特性和可用性保证。
- 缺点: 引入新的技术栈,同样需要谨慎处理与 Spring 代理的集成问题。
- 调整业务流程: 通过串行化处理(如消息队列)或减少并发操作来规避分布式锁。
- 优点: 可能简化并发控制。
- 缺点: 可能引入额外系统复杂度(消息队列),影响系统性能或实时性。
最终选择方案一,因为它直接针对分布式锁本身的不足和与 Spring 代理的交互问题,是后端工程师解决此类问题的首要思路。
7.问题总结
- 此次“attempt to unlock lock, not locked by current thread”异常在业务层方法中使用 Redis 分布式锁场景下的出现,是一次典型的分布式并发 Bug。它深刻揭示了在分布式环境下进行并发控制的复杂性,以及框架代理机制可能对底层同步逻辑产生的影响。必须深入理解分布式锁的原理和安全实现(原子释放、锁续期),并警惕其与 Spring 等框架代理结合时可能产生的“副作用”。通过构建健壮的分布式锁集成方案,才能确保系统在高并发分布式环境下的稳定运行。
相关文章:
Spring 代理与 Redis 分布式锁冲突:一次锁释放异常的分析与解决
Spring 代理与 Redis 分布式锁冲突:一次锁释放异常的分析与解决 Spring 代理与 Redis 分布式锁冲突:一次锁释放异常的分析与解决1. 问题现象与初步分析2 . 原因探究:代理机制对分布式锁生命周期的干扰3. 问题复现伪代码4. 解决方案࿱…...
vue Element-ui对图片上传和选用时的比例控制
vue Element-ui对图片上传和选用时的比例控制 在后台上传图片和选用已经上传的图片时,往往会因为图片的比例控制不到位导致在客户端渲染时效果差强人意,虽然可以在操作时选择合适的比例上传,但必要的控制还是能完成渲染时良好的体验…...
UE5在C++项目中判断不同平台
在Unreal Engine 5的C代码中,可以通过以下方法判断当前运行的平台(如Android、Windows、iOS),并根据平台执行不同的逻辑: 方法1:使用预处理器宏(编译时判断) Unreal Engine提供了一…...
用 CodeBuddy 实现「IdeaSpark 每日灵感卡」:一场 UI 与灵感的极简之旅
项目起点:一次随手的灵感 有时候,灵感稍纵即逝,尤其是面对屏幕发呆的时候。那天我忽然想到——要是能有一个每天弹出一句创意提示、灵感金句的应用就好了,最好配上简洁但有氛围感的 UI,像抽一张卡片一样,轻…...
std::ranges::views::as_const 和 std::ranges::as_const_view
std::ranges::views::as_const 和 std::ranges::as_const_view 是 C23 引入的视图适配器,用于生成一个不可变的视图,确保通过该视图访问元素时,元素被视为常量。以下是详细说明和示例: 基本概念 功能: 将输入范围的元素…...
3D 数据交换格式(.3DXML)简介
3DXML 是一种基于 XML 的 3D 数据交换格式,由达索系统(Dassault Systmes)开发,主要用于其 CATIA、SOLIDWORKS 和 3DEXPERIENCE 等产品中。 基本概述 全称:3D XML开发者:达索系统主要用途:3D…...
深度解析3D模型生成器:基于StyleGAN3与PyTorch3D的多风格生成工具开发实战
引言:跨模态生成的革命性突破 在元宇宙与数字孪生技术蓬勃发展的今天,3D内容生成已成为制约产业发展的关键瓶颈。传统建模方式依赖专业软件和人工操作,而基于深度学习的生成模型正颠覆这一范式。本文将深入解析如何构建支持多风格生成的3D模…...
DTAS 3D多约束装配助力悬架公差分析尺寸链计算:麦弗逊/双叉臂/多连杆/H臂一网打尽
摘要:汽车四轮定位参数与悬架密切相关。汽车悬架对于车辆的行驶性能、安全性和舒适性至关重要。DTAS 3D提供了各类型悬架的公差仿真分析方法。 关键字:DTAS 3D、前后悬架、公差仿真分析、 运动耦合 一、悬架公差分析综述 悬架是车身(或车架…...
CRMEB多商户预约服务上门师傅端
随着科技的不断发展,人们对于生活品质的要求也在不断提高。在这个过程中,各种便捷的上门服务应运而生,为我们的生活带来了极大的便利。而CRMEB多商户预约服务上门师傅端正是这样一款致力于为用户提供专业、高效、便捷的上门服务的应用。 一、…...
labview硬件开发板——LED流水灯
函数 : int DoSetV12( unsigned char chan, unsigned char state); 功能 :设置 OUT0—3 的输出状态,输入参数为 8 位字符型, Chan:4 位要设置的通道,0 对应 OUT1……3 对应 OUT4 ( 注意:开…...
linux——mysql故障排查与生产环境优化
目录 一,mysql数据库常见的故障 1,故障现象1 2,故障现象2 3,故障现象3 4,故障现象4 5,故障现象5 6,故障现象6 二&…...
MongoDB及spring集成
MongoDB 是一个基于 分布式文件存储 的开源 NoSQL 数据库系统 用文档存数据,每个文档可以看作是一个键值对集合,类似于 JSON 对象 MongoDB 支持索引以提高查询性能,并且可以在任何属性上创建索引 文档(Document) M…...
一发入魂:极简解决 SwiftUI 复杂视图未能正确刷新的问题(下)
概述 各位似秃非秃小码农们都知道,在 SwiftUI 中视图是状态的函数,这意味着状态的改变会导致界面被刷新。 但是,对于有些复杂布局的 SwiftUI 视图来说,它们的界面并不能直接映射到对应的状态上去。这就会造成一个问题:状态的改变并没有及时的引起 UI 的变化。 如上图所示…...
关于我在使用stream().toList()遇到的问题
关于我在使用stream().toList()遇到的问题 问题描述 在测试以上程序的时候抛出了空指针异常 于是我以为是我数据库中存在null字段,但查看后发现并不存在为null的数据 问题排查 起初我以为问题出现在sort排序方法这,事实也确实是,当我把s…...
如何通过生成式人工智能认证(GAI认证)提升自己的技能水平?
当生成式人工智能从实验室走向生产线,职场人正面临一个关键抉择:是被动等待技术浪潮的冲刷,还是主动构建适应未来的能力护城河?职业技能培训的终极目标,早已超越“掌握工具”的初级阶段,转向“构建技术认知体系”的深层需求。生成式人工智能认证(GAI认证)的兴起,正是这…...
通讯协议串口 | 485标准
485通讯(RS-485)详解 一、基本概念与核心原理 定义与标准 RS-485(又称EIA-485)是一种由美国电子工业协会(EIA)制定的差分信号串行通信标准,属于OSI模型的物理层协议。它专为工业环境设计&#…...
新能源充电桩智慧管理系统:未来新能源汽车移动充电服务发展前景怎样?
随着全球新能源汽车保有量的持续攀升,传统固定充电桩建设速度已难以满足用户日益增长的补能需求。在这一背景下,移动充电服务作为充电基础设施的重要补充,正展现出巨大的发展潜力。政策支持、技术进步(如快充、智能调度࿰…...
【强化学习】#6 n步自举法
主要参考学习资料:《强化学习(第2版)》[加]Richard S.Suttion [美]Andrew G.Barto 著 文章源文件:https://github.com/INKEM/Knowledge_Base 概述 n步时序差分方法是蒙特卡洛方法和时序差分方法更一般的推广。将单步Sarsa推广到n…...
双指针算法:原理与应用详解
文章目录 一、什么是双指针算法二、双指针算法的适用场景三、双指针的三种常见形式1. 同向移动指针2. 相向移动指针3. 分离指针 四、总结 一、什么是双指针算法 双指针算法(Two Pointers Technique)是一种在数组或链表等线性数据结构中常用的高效算法技…...
小土堆pytorch--神经网路的基本骨架(nn.Module的使用)卷积操作
小土堆pytorch–神经网路的基本骨架(nn.Module的使用) 对于官网nn.Module操作的解释 在pytorch官网可以看到 对于上述forward函数的解释: 示例代码 import torch from torch import nnclass Test(nn.Module): # 继承神经网路的基本骨架…...
数据库连接池技术与 Druid 连接工具类实现
目录 1. 数据库连接池简介 1.1. 什么是数据库连接池 1.2. 不使用数据库连接池可能存在的问题 1.3. JDBC数据库连接池的必要性 1.4. 数据库连接池的优点 1.5. 常用的数据库连接池 2. Druid连接池 2.1. Druid简介 2.2. Druid使用步骤 2.2.1. 第一步的步骤详解ÿ…...
chrome源码中WeakPtr 跨线程使用详解:原理、风险与最佳实践
base::WeakPtr 在 Chromium 中 不能安全地跨线程使用。这是一个很关键的点,下面详细解释原因及正确用法。 🔍原理与使用 ✅ 先说答案: base::WeakPtr 本质上是**线程绑定(thread-affine)**的。不能在多个线程之间创建…...
vue2使用three.js实现一个旋转球体
vue页面中 <div ref"container"></div>data声明 scene: null, camera: null, renderer: null, controls: null, rotationType: sphere, rotationTimer: null,backgroundImageUrl: https://mini-app-img-1251768088.cos.…...
社交平台推出IP关联机制:增强用户体验与网络安全的新举措
社交平台为我们提供与亲朋好友保持联系、分享生活点滴的便捷渠道,还成为了信息传播、观点交流的重要平台。然而,随着社交平台的普及,网络空间中的虚假信息、恶意行为等问题也日益凸显。为了应对这些挑战,许多社交平台相继推出IP关…...
sherpa-ncnn:音频处理跟不上采集速度 -- 语音转文本大模型
目录 1. 问题报错2. 解决方法 1. 问题报错 报错: An overrun occurred, which means the RTF of the current model on your board is larger than 1. You can use ./bin/sherpa-ncnn to verify that. Please select a smaller model whose RTF is less than 1 fo…...
【android bluetooth 协议分析 01】【HCI 层介绍 8】【ReadLocalVersionInformation命令介绍】
1. HCI_Read_Local_Version_Information 命令介绍 1. 功能(Description) HCI_Read_Local_Version_Information 命令用于读取本地 Bluetooth Controller 的版本信息,包括 HCI 和 LMP 层的版本,以及厂商 ID 和子版本号。 这类信息用…...
android13以太网静态ip不断断开连上问题
总纲 android13 rom 开发总纲说明 文章目录 1.前言2.log记录3.问题分析4.代码修改5.彩蛋1.前言 android13以太网静态ip不断断开连上,具体情况为保存静态以太网成功后,可以看到以太网链接成功的图标,但是几秒后会消失,出现断网,几秒后又出现,反复出现和消失。 2.log记录…...
UA 编译和建模入门教程(zhanzhi学习笔记)
一、使用SIOME免费工具建模 从西门子官网下载软件SIOS,需要注册登录,下载安装版就行。下载后直接安装就可以用了,如图: 安装完成后打开,开始建模,如图左上角有新建模型的按钮。 新建了新工程后,…...
系统架构设计-案例分析总结
系统架构设计-案例分析总结 2024年下半年系统架构设计师案例第1题 2022年下半年系统架构设计师案例第1题第2题 2021年下半年系统架构设计师案例第1题第2题 2024年下半年系统架构设计师案例 题:效用树可用性中ping/echo策略和心跳策略比较 第1题 阅读以下关于面向质…...
【QT】一个界面中嵌入其它界面(三)
在 Qt 中,通过 UI 设计 或 代码布局 实现界面 A 中同时显示界面 B 和 C,并精确指定它们的位置,可以通过以下两种方式实现。以下是详细步骤和完整代码: 方法 0:使用 Qt Designer 可视化布局 通过 Qt Designer 拖拽控件…...
实战教程:影刀RPA采集闲鱼商品并分享钉钉
1.实战目标 采集字段: 采集时间商品ID商品标题标价商品链接 采集的第一个品 可通过钉钉分享给好友 也可以通过钉钉群通知指令,发送到指定群 2.实战代码 2.1 主体代码 2.2 采集初始化 先初始化环境 这一步骤主要是连接手机,能使用影刀RPA操…...
多模态大语言模型arxiv论文略读(八十二)
Emotion-LLaMA: Multimodal Emotion Recognition and Reasoning with Instruction Tuning ➡️ 论文标题:Emotion-LLaMA: Multimodal Emotion Recognition and Reasoning with Instruction Tuning ➡️ 论文作者:Zebang Cheng, Zhi-Qi Cheng, Jun-Yan H…...
常见排序算法整理(Java实现)
1.冒泡排序(Bubble Sort) 原理 重复遍历数组,比较相邻元素,若顺序错误则交换。每趟将最大元素"冒泡"到末尾。 每次遍历保证了最大元素被放在最后,所以内层循环不需要遍历到最后的位置。 代码实现 public …...
c++字符串常用语法特性查询示例文档(二)
在 C中,除了std::string和std::string_view,还有其他一些与字符串相关的类型,它们各自针对不同的场景进行了优化。以下是一些常见的字符串类型及其使用方式和适用场景的汇总。 紧接上篇 c字符串常用语法特性查询示例文档(一&#…...
10.14 Function Calling与Tool Calling终极解析:大模型工具调用的5大核心差异与实战优化
Function Calling vs Tool Calling:大模型工具调用机制深度解析 关键词:Function Calling 原理, Tool Calling 实现, @tool 装饰器, ToolMessage 机制, 工具调用优化 1. 核心概念对比分析 #mermaid-svg-uDxSPB1CoQrHDxrT {font-family:"trebuchet ms",verdana,ari…...
opencascade如何保存选中的面到本地
环境:occ 7.6 需求场景:用户点击了一个TopoDS_Shape,还选中了其中一个面,这时候他点了保存。用户下次打开模型文件时,我们的viewer窗口要恢复上次的选中状态。 核心问题:如何把用户选中的面保存,…...
CSS 单位详解:px、rem、em、vw/vh 的区别与使用场景
CSS 单位详解:px、rem、em、vw/vh 的区别与使用场景 在 CSS 中,各种单位有不同的特性和适用场景,理解它们的区别对实现响应式布局至关重要。 1. 绝对单位 px 特点: 像素(Pixel)是绝对长度单位1px 对应屏…...
YOLO模型predict(预测/推理)的参数设置
上一章描述了预测初体验,基本可以使用现有的yolo模型进行预测/推理。本次我们了解一下这个过程中的参数的作用。 1.参数示例 conf=0.68 :表示模型识别这个东西是车的概率为68% 。一般默认的情况下,概率小于25%的就不显示了。 1)调整一下python的代码的参数如下,可以预测图…...
MATLAB中NLP工具箱支持聚类算法
文章目录 前言一、层次聚类(Hierarchical Clustering)二、DBSCAN(基于密度的空间聚类)三、高斯混合模型(GMM)四、谱聚类(Spectral Clustering)五、模糊 C 均值(Fuzzy C-M…...
甘特图工具怎么选?免费/付费项目管理工具对比测评(2025最新版)
2025年甘特图工具的全面指南 在项目管理领域,甘特图作为最直观的任务规划和进度追踪工具,已成为团队协作和项目执行的核心手段。随着数字化技术的快速发展,2025年的甘特图工具市场呈现出前所未有的多元化和智能化趋势。从开源软件到云端协作…...
Google设置app-ads.txt
问题: 应用上架后admob后台显示应用广告投放量受限,需要设置app-ads.txt才行。 如何解决: 官方教程: 看了下感觉不难,创建一个txt,将第二条的代码复制进行就得到app-ads.txt了。 然后就是要把这个txt放到哪才可以…...
Swift 二分查找实战:精准定位第一个“Bug版本”(LeetCode 278)
文章目录 摘要描述示例 题解答案(Swift)题解代码分析示例测试及结果输出结果: 时间复杂度分析空间复杂度分析总结 摘要 在版本迭代频繁的项目开发中,定位引入 bug 的第一个版本是一项高频任务。LeetCode 第278题“第一个错误的版…...
《AI革命重塑未来五年:医疗诊断精准度翻倍、自动驾驶事故锐减90%,全球科技版图加速变革》
1. 显著突破领域:AI 引发医疗与自动驾驶的范式变革 医疗领域的突破: AI正深刻改变医学研发和临床诊疗模式。在新药研发现代生物学中,DeepMind公司推出的 AlphaFold AI 模型在蛋白质折叠预测上取得了重大突破,被视为解决了困扰科学…...
【盈达科技】AICC™系统:重新定义生成式AI时代的内容竞争力
盈达科技AICC™系统:重新定义生成式AI时代的内容竞争力 ——全球首款AI免疫化内容中台的技术革命与商业实践 一、技术破局:AICC™系统如何重构AI内容生态 1. 技术架构:四大引擎构建闭环护城河 盈达科技AICC™(AI-Immunized Con…...
芯驰科技与安波福联合举办技术研讨会,深化智能汽车领域合作交流
5月15日,芯驰科技与全球移动出行技术解决方案供应商安波福(Aptiv)在上海联合举办以“芯智融合,共赢未来”为主题的技术研讨会。会上,双方聚焦智能座舱与智能车控的发展趋势,展开深入交流与探讨,…...
开发 前端搭建npm v11.4.0 is known not to run on Node.js v14.18.1.
错误nodejs 和npm 版本不一致 ERROR: npm v11.4.0 is known not to run on Node.js v14.18.1. This version of npm supports the following node versions: ^20.17.0 || >22.9.0. You can find the latest version at https://nodejs.org/. ERROR: D:\softTool\node-v14…...
关于systemverilog中在task中使用force语句的注意事项
先看下面的代码 module top(data);logic clk; inout data; logic temp; logic sampale_data; logic [7:0] data_rec;task send_data(input [7:0] da);begin(posedge clk);#1;force datada[7];$display(data);(posedge clk);#1;force datada[6]; $display(data); (posed…...
国产 iPaaS 与国外 iPaaS 产品相比如何?以谷云科技为例
iPaaS(Integration Platform as a Service)作为企业集成的关键技术,受到了广泛关注。国产 iPaaS 产品与国外 iPaaS 产品存在诸多差异,以下将从多个方面进行分析探讨。 一、技术架构与创新 国外 iPaaS 产品往往技术架构成熟且先进…...
低功耗:XILINX FPGA如何优化功耗?
优化Xilinx FPGA及其外围电路的功耗需要从硬件设计、软件配置和系统级优化三个层面综合考虑。以下是具体的优化策略,涵盖硬件和软件方面: 一、硬件层面的功耗优化 选择低功耗FPGA型号 选择Xilinx低功耗系列芯片,如7系列中的Artix-7ÿ…...
从纸质契约到智能契约:AI如何改写信任规则与商业效率?——从智能合约到监管科技,一场颠覆传统商业逻辑的技术革命
一、传统合同的“低效困境”:耗时、昂贵、风险失控 近年来,全球商业环境加速向数字化转型,但合同管理却成为企业效率的“阿喀琉斯之踵”。据国际商会(International Chamber of Commerce)数据显示,全球企业…...