当前位置: 首页 > article >正文

SpringBoot 多事务并发控制:悲观锁与乐观锁全面详解

前面我们系统学习了 SpringBoot 声明式事务Transactional、编程式事务TransactionTem)plate、事务传播行为、隔离级别以及事务失效的全套解决方案核心解决的是「单个业务、单次请求」的事务原子性、一致性问题。但、项目上线后真正的线上隐患往往不是单线程的事务问题而是高并发场景下多事务同时操作同一条数据引发的各种数据安全问题。比如这些高频线上场景你一定遇到过或听过• 电商秒杀1000人同时抢购100件商品最终超卖50件库存显示负数• 支付场景用户同时发起两次支付余额被重复扣减出现负数• 积分兑换多线程同时兑换积分积分被重复扣减或兑换到超出库存的商品• 订单状态修改多线程同时修改订单状态比如“待支付”→“已支付”、“待支付”→“已取消”导致订单状态错乱。很多同学会陷入一个致命误区只要加了 Transactional 事务数据就绝对安全。事实恰恰相反Spring 事务的 ACID 特性只能保证「单个事务内部」的原子性、一致性无法解决「多个事务并发修改同一条数据」的问题。想要解决高并发下的多事务数据安全必须依靠数据库层面的并发控制方案——悲观锁与乐观锁。为什么 Transactional 解决不了并发修改问题在讲锁之前我们必须先搞懂核心问题为什么加了事务还是会出现超卖、重复扣减结合最经典的「库存超卖案例」拆解底层原因一看就懂。1. 超卖案例场景商品库存初始值为 10两个用户同时抢购线程A、线程B每个用户抢购1件核心业务代码仅加事务未加锁Service public class StockService { Autowired private StockMapper stockMapper; // 仅加事务未加锁 Transactional(rollbackFor Exception.class) public void decreaseStock(Long productId) { // 1. 查询当前库存 Stock stock stockMapper.selectByProductId(productId); if (stock null || stock.getStock() 0) { throw new BusinessException(库存不足); } // 2. 扣减库存stock stock - 1 int rows stockMapper.decreaseStock(productId); if (rows 0) { throw new BusinessException(库存扣减失败); } } }高并发下的执行流程线程A、线程B同时执行1. 线程A、线程B同时进入事务执行「查询库存」操作此时数据库隔离级别为 READ COMMITTED默认两个线程都读到库存 102. 线程A先执行扣减操作stock 10 - 1 9执行完毕等待提交3. 线程B紧接着执行扣减操作基于读到的旧库存 10执行 stock 10 - 1 9执行完毕等待提交4. 线程A、线程B先后提交事务最终库存变为 9而非 8。最终结果两个用户都抢购成功但库存只扣减了1次出现超卖问题数据严重不一致。2. 核心原因出现这个问题的核心原因有两个缺一不可• ① 事务隔离级别的局限性MySQL 默认隔离级别是 READ COMMITTED读已提交只能解决「脏读」无法解决「不可重复读」和「并发更新覆盖」。多个事务同时读取同一条数据的旧值基于旧值做修改提交后互相覆盖导致数据错误• ② 事务执行的“非原子性”相对于多事务单个事务内部是原子性的但多个事务并发执行时「查询库存」和「扣减库存」这两个操作对于多事务来说并不是原子操作——两个事务可以同时执行“查询”再先后执行“扣减”导致基于旧数据修改。补充说明即使把事务隔离级别提升到 REPEATABLE_READ可重复读也无法彻底解决这个问题。因为可重复读解决的是“同一个事务内多次读取数据一致”但多个事务之间依然可以同时读取旧数据执行修改操作还是会出现并发覆盖。3. 结论Spring 事务的核心作用是保证「单个事务内部」的原子性、一致性而锁机制的核心作用是保证「多个事务并发操作同一条数据」的一致性。两者缺一不可事务是基础锁是高并发下的补充。二、锁的核心概念悲观锁 vs 乐观锁解决多事务并发修改问题核心是「阻止多个事务同时修改同一条数据」或者「让多个事务有序修改同一条数据」。根据“是否提前阻止并发”分为两种设计思想悲观锁、乐观锁。用通俗的比喻理解非常好记• 悲观锁假设一定会发生并发冲突提前加锁阻止其他事务修改数据直到当前事务执行完毕释放锁。比如抢东西时先把东西抱在怀里别人拿不到直到自己用完• 乐观锁假设不会发生并发冲突不提前加锁而是在修改数据时检查数据是否被其他事务修改过如果没有被修改就执行修改如果被修改就拒绝修改或重试。比如抢东西时不先拿直到要付钱时才检查东西是否还在还在就拿走不在就放弃。1. 悲观锁Pessimistic Lock核心思想悲观锁锁的是“数据”提前锁定目标数据禁止其他事务对其进行修改、删除操作直到当前事务提交或回滚释放锁。核心特点• 优点并发冲突时直接阻止不会出现数据不一致安全性高• 缺点提前加锁会阻塞其他事务降低并发性能如果锁的粒度太大如表锁会导致大量事务阻塞引发性能瓶颈• 底层实现依赖数据库自身的锁机制行锁、表锁由数据库层面控制。常见应用场景写操作频繁、并发冲突概率高的场景如下单支付、余额扣减、库存扣减。2. 乐观锁Optimistic Lock核心思想乐观锁锁的是“版本”不提前加锁而是给数据添加一个“版本标识”如版本号、时间戳修改数据时检查版本标识是否和自己查询时一致一致则修改不一致则拒绝或重试。核心特点• 优点不阻塞其他事务并发性能高无需依赖数据库锁机制实现简单• 缺点存在“ABA问题”后面详细讲并发冲突概率高时会出现大量重试反而降低性能• 底层实现由开发者手动实现版本号、时间戳不依赖数据库锁。常见应用场景读操作频繁、写操作少、并发冲突概率低的场景如商品详情查询、积分查询、订单详情修改。三、悲观锁实战3种实现方式SpringBoot MySQL悲观锁的实现依赖 MySQL 自身的锁机制SpringBoot 中无需额外导入依赖只需在 SQL 或代码中配置锁逻辑即可。根据锁的粒度分为「行锁」和「表锁」实际开发中优先使用「行锁」粒度细并发性能高表锁仅用于特殊场景。先准备环境直接复用前面的库存表可直接复制-- 库存表核心字段商品ID、库存数量 CREATE TABLE stock ( id bigint NOT NULL AUTO_INCREMENT COMMENT 主键ID, product_id bigint NOT NULL COMMENT 商品ID, stock int NOT NULL DEFAULT 0 COMMENT 库存数量, create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), UNIQUE KEY idx_product_id (product_id) COMMENT 商品ID唯一索引 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT商品库存表; -- 插入测试数据商品ID1库存10 INSERT INTO stock (product_id, stock) VALUES (1, 10);SpringBoot 环境准备依赖、配置和前面事务实战一致导入 mybatis-spring-boot-starter、mysql-connector-j 依赖配置 application.yml 数据源此处省略可直接复用。方式1MySQL 行锁—— select ... for update这是企业开发中最常用的悲观锁实现方式属于「行锁」只锁定当前查询的行数据不影响其他行并发性能高。核心原理在查询数据时加上for update关键字MySQL 会对查询到的行数据加行锁其他事务想要修改、删除该行吗数据会被阻塞直到当前事务提交或回滚释放锁。✅ 注意事项•select ... for update必须在事务内执行否则锁会立即释放无效• 必须通过「索引」查询如 product_id 唯一索引否则会升级为表锁阻塞所有行的操作• 锁的释放时机事务提交commit或回滚rollback时自动释放锁。✅ 完整代码// 1. Mapper 接口添加带 for update 的查询方法 public interface StockMapper { // 带行锁的查询select ... for update Stock selectByProductIdForUpdate(Param(productId) Long productId); // 库存扣减 int decreaseStock(Param(productId) Long productId); } // 2. Mapper XML核心 SQL select idselectByProductIdForUpdate resultTypecom.example.concurrency.entity.Stock SELECT id, product_id, stock FROM stock WHERE product_id #{productId} FOR UPDATE -- 加行锁 /select update iddecreaseStock UPDATE stock SET stock stock - 1 WHERE product_id #{productId} AND stock 0 /update // 3. Service 层事务 行锁 Service Slf4j public class StockService { Autowired private StockMapper stockMapper; // 必须加事务否则 for update 锁会立即释放 Transactional(rollbackFor Exception.class) public void decreaseStockWithPessimisticLock(Long productId) { // 1. 查询库存并加行锁其他事务会被阻塞直到当前事务结束 Stock stock stockMapper.selectByProductIdForUpdate(productId); if (stock null || stock.getStock() 0) { throw new BusinessException(库存不足); } // 2. 扣减库存此时该数据已被锁定其他事务无法修改 int rows stockMapper.decreaseStock(productId); if (rows 0) { throw new BusinessException(库存扣减失败); } log.info(库存扣减成功商品ID{}剩余库存{}, productId, stock.getStock() - 1); } } // 4. Controller 层接口测试 RestController RequestMapping(/stock) public class StockController { Autowired private StockService stockService; PostMapping(/decrease/{productId}) public ResultVO decreaseStock(PathVariable Long productId) { try { stockService.decreaseStockWithPessimisticLock(productId); return ResultVO.success(库存扣减成功); } catch (BusinessException e) { return ResultVO.fail(e.getMessage()); } catch (Exception e) { log.error(库存扣减异常, e); return ResultVO.fail(系统异常请稍后重试); } } }✅ 高并发验证压测用 JMeter 压测1000个并发请求商品ID1初始库存10最终库存0无超卖、无重复扣减验证成功。执行流程多个并发请求同时进入事务第一个请求查询库存并加行锁其他请求会阻塞在「select ... for update」这一步直到第一个事务提交释放锁下一个请求才能获取锁、执行操作依次类推实现有序扣减。方式2MySQL 表锁—— lock table表锁是粒度最大的悲观锁锁定整个表其他事务无法对该表执行任何 insert、update、delete 操作并发性能极差仅用于「全表更新、批量操作」等特殊场景。✅ 实战代码Service public class StockService { Autowired private JdbcTemplate jdbcTemplate; Autowired private StockMapper stockMapper; Transactional(rollbackFor Exception.class) public void decreaseStockWithTableLock(Long productId) { try { // 1. 加表锁锁定整个 stock 表 jdbcTemplate.execute(LOCK TABLE stock WRITE); // 2. 查询库存 Stock stock stockMapper.selectByProductId(productId); if (stock null || stock.getStock() 0) { throw new BusinessException(库存不足); } // 3. 扣减库存 int rows stockMapper.decreaseStock(productId); if (rows 0) { throw new BusinessException(库存扣减失败); } } finally { // 4. 释放表锁必须在 finally 中释放防止事务异常导致锁未释放 jdbcTemplate.execute(UNLOCK TABLES); } } }❌ 缺点锁定整个表并发性能极差1000个并发请求会排队执行导致接口响应时间过长甚至超时日常开发中严禁使用。方式3Spring 声明式锁—— Lock结合 Spring Data JPA如果项目中使用 Spring Data JPA无需写原生 SQL可通过 Lock 注解快速实现悲观锁本质也是底层调用 MySQL 的 select ... for update。✅ 实战代码JPA 场景// 1. Repository 接口添加 Lock 注解 public interface StockRepository extends JpaRepositoryStock, Long { // Lock(LockModeType.PESSIMISTIC_WRITE) 对应 select ... for update行锁 Lock(LockModeType.PESSIMISTIC_WRITE) Query(SELECT s FROM Stock s WHERE s.productId :productId) OptionalStock findByProductIdWithLock(Param(productId) Long productId); } // 2. Service 层 Service public class StockService { Autowired private StockRepository stockRepository; Transactional(rollbackFor Exception.class) public void decreaseStockWithJpaLock(Long productId) { // 查询库存并加行锁 Stock stock stockRepository.findByProductIdWithLock(productId) .orElseThrow(() - new BusinessException(商品不存在)); if (stock.getStock() 0) { throw new BusinessException(库存不足); } // 扣减库存 stock.setStock(stock.getStock() - 1); stockRepository.save(stock); } }✅ 说明Lock(LockModeType.PESSIMISTIC_WRITE) 是写锁行锁适合修改操作如果是查询操作可使用 Lock(LockModeType.PESSIMISTIC_READ)读锁共享锁。四、乐观锁实战2种实现方式乐观锁不依赖数据库锁机制由开发者手动实现核心是「版本标识」。常用的两种实现方式版本号机制最通用、时间戳机制简化版实际开发中优先使用版本号机制。先修改库存表添加版本号字段乐观锁的关键-- 给 stock 表添加版本号字段乐观锁核心 ALTER TABLE stock ADD COLUMN version int NOT NULL DEFAULT 1 COMMENT 版本号乐观锁用; -- 同步测试数据版本号默认1 UPDATE stock SET version 1 WHERE product_id 1;方式1版本号机制核心原理给数据添加一个版本号version初始值为1• 查询数据时同时查询版本号• 修改数据时在 update 语句中添加条件version 查到的版本号• 如果修改成功影响行数1说明数据未被其他事务修改同时将版本号1• 如果修改失败影响行数0说明数据已被其他事务修改拒绝修改或重试。✅ 完整代码// 1. 实体类添加 version 字段 Data TableName(stock) public class Stock { private Long id; private Long productId; private Integer stock; private Integer version; // 乐观锁版本号 private Date createTime; private Date updateTime; } // 2. Mapper 接口 public interface StockMapper { // 查询库存同时查询版本号 Stock selectByProductId(Param(productId) Long productId); // 乐观锁扣减库存核心where 条件添加 version #{version} int decreaseStockWithVersion(Param(productId) Long productId, Param(version) Integer version); } // 3. Mapper XML核心 SQL select idselectByProductId resultTypecom.example.concurrency.entity.Stock SELECT id, product_id, stock, version FROM stock WHERE product_id #{productId} /select update iddecreaseStockWithVersion UPDATE stock SET stock stock - 1, version version 1 -- 版本号1 WHERE product_id #{productId} AND stock 0 AND version #{version} -- 核心条件版本号匹配 /update // 4. Service 层核心重试机制可选 Service Slf4j public class StockService { Autowired private StockMapper stockMapper; // 无需加锁事务可选根据业务需求添加 Transactional(rollbackFor Exception.class) public void decreaseStockWithOptimisticLock(Long productId) { // 循环重试可选解决并发冲突时修改失败的问题 int retryCount 3; // 最多重试3次 while (retryCount 0) { // 1. 查询库存和版本号 Stock stock stockMapper.selectByProductId(productId); if (stock null || stock.getStock() 0) { throw new BusinessException(库存不足); } // 2. 乐观锁扣减库存版本号匹配才修改 int rows stockMapper.decreaseStockWithVersion(productId, stock.getVersion()); if (rows 0) { // 修改成功退出循环 log.info(库存扣减成功商品ID{}剩余库存{}版本号{}, productId, stock.getStock() - 1, stock.getVersion() 1); return; } // 修改失败重试重试次数减1 retryCount--; log.warn(库存扣减失败重试次数{}商品ID{}, retryCount, productId); // 可选重试间隔避免频繁重试减轻数据库压力 try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } // 重试3次仍失败抛出异常 throw new BusinessException(库存扣减失败请稍后重试); } } // 5. Controller 层和悲观锁一致省略✅ 高并发验证1000个并发请求商品ID1初始库存10最终库存0无超卖部分请求会因版本号不匹配重试最终都能成功扣减重试次数控制在3次内避免无限重试。✅ 关键细节重试机制是可选的根据业务场景决定——如果是秒杀场景可拒绝重试直接返回“抢购失败”如果是普通库存扣减可添加重试机制提升成功率。方式2时间戳机制核心原理用数据的 update_time更新时间作为版本标识替代版本号原理和版本号机制一致——查询数据时获取 update_time修改时判断 update_time 是否和查询时一致。✅ 实战代码核心 SQL// Mapper XML 核心 update 语句 update iddecreaseStockWithTimestamp UPDATE stock SET stock stock - 1, update_time CURRENT_TIMESTAMP WHERE product_id #{productId} AND stock 0 AND update_time #{updateTime} -- 用更新时间作为版本标识 /update❌ 缺点时间戳精度问题如 MySQL 时间戳精确到秒如果多个事务在同一秒内修改数据会出现误判认为数据未被修改且无法直观看到数据被修改的次数排查问题不便日常开发中不推荐。乐观锁的 ABA 问题✅ 什么是 ABA 问题场景线程A查询数据stock10version1线程B修改数据stock9version2然后线程B又修改数据stock10version3此时线程A执行修改发现 version1 ! 3修改失败——这是正常情况。但如果线程C在线程A查询后修改数据stock9version2再修改回stock10version3线程A执行修改时虽然数据最终值和查询时一致但数据已经被修改过线程A却不知道这就是「ABA问题」。✅ 解决方案2种• 方式1使用「版本号时间戳」双重校验推荐既判断版本号也判断更新时间避免ABA问题• 方式2使用「原子引用AtomicReference」记录数据的修改记录不仅仅判断最终值还判断修改过程适合Java内存中的乐观锁数据库层面不常用。✅ 数据库层面解决方案实战代码-- 修改 update 语句添加双重校验 update iddecreaseStockWithDoubleCheck UPDATE stock SET stock stock - 1, version version 1, update_time CURRENT_TIMESTAMP WHERE product_id #{productId} AND stock 0 AND version #{version} AND update_time #{updateTime} -- 双重校验版本号更新时间 /update五、悲观锁 vs 乐观锁 深度对比这是本篇核心重点结合企业实战场景从10个核心维度做全面对比帮你快速选型避免踩坑。对比维度悲观锁行锁为主乐观锁版本号为主设计思想假设并发冲突一定会发生提前加锁假设并发冲突不会发生修改时校验底层依赖依赖数据库自身锁机制行锁、表锁开发者手动实现版本号、时间戳不依赖数据库锁并发性能较低会阻塞其他事务锁竞争激烈时性能下降明显较高不阻塞其他事务并发冲突时仅重试无阻塞开销数据安全性高直接阻止并发修改不会出现数据不一致较高存在ABA问题可解决并发冲突高时可能出现重试失败实现复杂度低只需在SQL中添加 for update无需额外代码中需添加版本号字段编写校验逻辑可选重试机制锁粒度细行锁或粗表锁可灵活选择无锁仅通过版本号校验粒度极细适用场景写操作频繁、并发冲突概率高下单、支付、余额扣减读操作频繁、写操作少、并发冲突概率低查询、详情修改常见问题死锁、锁升级、阻塞超时ABA问题、重试失败、并发冲突高时性能下降性能开销锁的获取、释放开销阻塞时的线程切换开销重试开销并发冲突时无锁获取开销SpringBoot 整合难度低无需额外依赖SQL中添加 for update 即可中需修改表结构添加版本号编写校验逻辑选型核心原则必记根据并发冲突概率和读写比例选型——写多读少、冲突高用悲观锁读多写少、冲突低用乐观锁。没有绝对的优劣只有是否适配业务场景。六、文末小结多事务并发控制是企业级高并发项目的必备知识点核心是「锁机制」悲观锁和乐观锁没有绝对的优劣关键是适配业务场景。总结核心要点•1. 事务解决「单个事务内部」的数据一致性锁解决「多事务并发」的数据一致性两者缺一不可•2. 悲观锁提前加锁阻塞事务安全高适合写多读少、冲突高的场景常用 select ... for update 行锁•3. 乐观锁修改校验不阻塞事务性能高适合读多写少、冲突低的场景常用版本号机制•4. 高并发优化锁粒度优化、缓存优化、重试机制、分布式锁避免踩死锁、锁升级、ABA问题等坑•5. 选型原则根据读写比例和并发冲突概率选择合适的锁方案不要盲目追求高性能。本篇文章的所有代码均可直接复制上线使用建议结合实际业务场景灵活调整锁方案和优化技巧。如果在项目中遇到并发锁相关的问题或者有其他疑问欢迎在评论区留言交流一起避坑、一起进步别忘了点赞在看收藏三连关注我解锁更多 SpringBoot 高并发实战干货不见不散❤️

相关文章:

SpringBoot 多事务并发控制:悲观锁与乐观锁全面详解

前面我们系统学习了 SpringBoot 声明式事务(Transactional)、编程式事务(TransactionTem)plate)、事务传播行为、隔离级别以及事务失效的全套解决方案,核心解决的是「单个业务、单次请求」的事务原子性、一致性问题。但…...

别再只pip install了!深度解析Kaggle环境管理的底层逻辑与自定义秘籍

别再只pip install了!深度解析Kaggle环境管理的底层逻辑与自定义秘籍 当你在Kaggle上复现论文代码时,是否经历过这样的困境:pip install -r requirements.txt后满屏红色报错,不同Python版本间的依赖冲突让你手足无措?或…...

一份文档引发的连锁命令执行、从一个文档到全校三要素泄露和RCE

0x01 简介 某 211 高校业务系统的一次完整渗透测试。攻击者从系统公开的操作手册文档中获取关键账号规则,成功登录普通学生账号;随后通过修改角色 ID 实现垂直越权,新建管理员账号并进入后台,进一步构造数据包提权至超级管理员&a…...

IAR 9.2 主题设置踩坑实录:从字体失效到关键字高亮,我的完整配置流程

IAR 9.2 主题定制深度指南:从字体陷阱到语法高亮优化 第一次在IAR 9.2中尝试自定义主题时,我本以为会像其他主流IDE那样简单——直到发现字体设置完全失效、关键字高亮混乱不堪。经过三天反复试验和源码分析,终于摸清了这套主题系统的运作机制…...

自适应滤波入门避坑指南:从维纳滤波到LMS,别再混淆最陡下降和梯度下降了

自适应滤波算法实战解析:从理论误区到MATLAB仿真优化 刚接触自适应滤波时,总会被各种相似术语搞得晕头转向——维纳滤波、最陡下降法、LMS算法,它们之间到底有什么联系和区别?更让人困惑的是,许多教材把"最陡下降…...

终极Minecraft启动器指南:UltimMC让你的游戏体验更自由

终极Minecraft启动器指南:UltimMC让你的游戏体验更自由 【免费下载链接】Launcher Offline Minecraft launcher. 项目地址: https://gitcode.com/gh_mirrors/lau/Launcher UltimMC是一款功能强大的Minecraft自定义启动器,专为追求自由灵活游戏体验…...

别再只改YAML了!手把手教你从零实现YOLOv8的MSAM注意力模块(附完整代码)

从零构建YOLOv8的MSAM注意力模块:多尺度特征融合实战指南 在目标检测领域,YOLOv8凭借其出色的速度和精度平衡成为工业界的热门选择。但当你面对复杂场景中的多尺度目标时,是否发现模型对小物体或遮挡目标的检测效果不尽如人意?传统…...

手把手教你用STM32的FSMC驱动AD7606(附完整电路图与代码)

STM32与AD7606高速数据采集系统实战指南 在工业自动化、电力监测和医疗设备等领域,高精度多通道数据采集系统扮演着关键角色。AD7606作为一款16位8通道同步采样ADC,配合STM32的FSMC接口,能够构建出性能优异的数据采集解决方案。本文将深入探讨…...

ESP32按键防抖实战:用硬件消抖电路+软件延时解决LED闪烁问题

ESP32按键防抖实战:硬件消抖电路与软件延时双重保障方案 当你在深夜调试ESP32项目时,LED灯突然不受控制地闪烁,按键反应迟钝或误触发——这很可能是机械按键抖动在作祟。作为物联网开发中最基础的输入设备,机械按键的抖动问题困扰…...

【解构】 Claude 同模型双人格架构:对比 Anthropic 通用版与 Design 版 System Prompt 的工程差异

关键词:Claude Opus 4.7 | Claude Design | System Prompt | Agent 架构 | Prompt Engineering | Multi-Persona 你读完能得到: Anthropic 如何用同一个模型 两份 prompt 做出两个产品的完整分析7 个工程维度的对照表(身份/主动性/提问/格式…...

别再只用PBKDF2了!聊聊国密标准GMT0091里的SM4和HMAC-SM3怎么用

国密算法实战:从PBKDF2到HMAC-SM3与SM4-CBC的迁移指南 金融级应用开发中,密钥派生与数据加密方案的选择直接影响系统安全性。当项目需要满足国密标准合规要求时,开发者常面临从国际通用算法向SM系列算法迁移的技术挑战。本文将手把手演示如何…...

从‘Push to Trip’红色按钮讲起:手把手教你进行漏电断路器功能测试与日常维护

从‘Push to Trip’红色按钮讲起:手把手教你进行漏电断路器功能测试与日常维护 当你面对配电箱里那个神秘的红色按钮时,是否曾犹豫过该不该按下去?作为家庭用电安全的第一道防线,漏电断路器上的每个设计细节都暗藏玄机。本文将带你…...

告别手动编译!用Cygwin一键搞定ADI官方HDL库,Vivado 2018.2工程搭建效率翻倍

用Cygwin自动化构建ADI HDL库:Vivado工程搭建效率革命 在FPGA开发领域,时间就是竞争力。当我们面对ADI官方提供的丰富HDL库时,传统手动编译方式往往让工程师陷入"等待-调试-再等待"的恶性循环。以AD9361ZC706这样的典型工程为例&am…...

STM32 HAL库实战:避开ADC按键的那些‘坑’,从滤波到防抖的稳定方案

STM32 HAL库实战:ADC按键稳定性优化全攻略 在嵌入式开发中,ADC按键因其节省IO资源的特性而广受欢迎,但实际应用中常遇到采样波动、误触发等问题。本文将分享一套经过实战检验的稳定性优化方案,涵盖硬件校准、软件滤波和防抖处理等…...

手把手教你用MCUXpresso为i.MX RT1062创建第一个工程(从SDK获取到点灯调试)

从零开始玩转i.MX RT1062:MCUXpresso环境搭建与LED控制实战 拿到一块i.MX RT1062评估板时,很多嵌入式开发者会面临两个挑战:如何快速熟悉这个跨界MCU的独特架构,以及如何在MCUXpresso IDE中完成从工程创建到硬件调试的全流程。本…...

用Modbus Poll/Slave和串口助手调试STM32 Modbus主从机的完整流程

用Modbus Poll/Slave和串口助手调试STM32 Modbus主从机的完整流程 在工业自动化领域,Modbus协议因其简单可靠的特点成为最常用的通信协议之一。对于嵌入式开发者而言,掌握Modbus协议的调试技巧至关重要。本文将详细介绍如何使用Modbus Poll、Modbus Slav…...

AGI如何7×24小时守护长江生态?:基于卫星+IoT+多模态大模型的污染溯源实战框架

第一章:AGI驱动的长江生态全天候守护范式 2026奇点智能技术大会(https://ml-summit.org) 传统生态监测依赖人工巡检与离散传感器网络,难以应对长江流域跨省域、多尺度、强动态的水文—生物—人类活动耦合挑战。AGI驱动的守护范式通过具身感知、因果推理…...

用AD7124-4/8做高精度RTD测温?别只看精度,供电和基准电压的坑先避开

AD7124高精度RTD测温系统设计:从电源架构到基准电压的工程实践 在工业温度测量领域,铂电阻(RTD)因其出色的线性度和稳定性成为首选传感器之一。而要实现0.01C级别的测量分辨率,AD7124系列Σ-ΔADC常被工程师视为理想选择——直到他们在实际项…...

深度剖析:导致AI项目失败的五大核心因素与系统化解决方案

AI项目失败率高企,根源往往不在算法,而在系统性的工程、组织与价值错配。本文将深度剖析五大核心因素,并提供可落地的解决方案。同时,结合CAIE注册人工智能工程师认证的能力框架,说明系统化学习如何帮助从业者规避这些陷阱。 一、价值错配:解决了一个“完美”的非问题 现…...

深度策略:结合内部挖掘、校园照片与行业人脉,构建动态更新的AI人才储备体系

在人工智能技术日新月异的当下,企业间的人才争夺早已从“抢简历”升级为“抢潜力”。传统的招聘节奏往往滞后于技术迭代——等你看到简历时,真正的高手已被先行者锁定。因此,一套能动态感知、主动培育、持续连接的AI人才储备体系,正成为组织竞争力的核心护城河。 本文将围…...

别再凭感觉画板了!PCB布局布线这10个坑,新手工程师最容易踩

PCB设计避坑指南:新手工程师必须掌握的10个布局布线技巧 刚接触PCB设计的新手工程师常常会陷入一个误区——认为只要电路原理正确,板子画出来就能正常工作。这种想法往往会导致后期调试时遇到各种"玄学"问题:信号不稳定、EMI超标、…...

Vue v-slot → 用 VuReact 转换后变成这样的 React 代码

VuReact 是一个能将 Vue 3 代码编译为标准、可维护 React 代码的工具。今天就带大家直击核心:Vue 中常见的 v-slot 指令经过 VuReact 编译后会变成什么样的 React 代码? 前置约定 为避免示例代码冗余导致理解偏差,先明确两个小约定&#xf…...

Claude Design的系统提示词#设计经验总结

Shadow:研究下Claude Design的系统提示词,有不少经验值得参考⬇️1. 角色定位清晰,边界明确✅ "专家设计师 用户管理者"的协作关系 ✅ "HTML是工具,媒介可变"的灵活输出观 ✅ 明确拒绝的场景(版权…...

内容即世界,世界即产品:HappyOyster。即将开启创作者经济新范式

4月16日,阿里 ATH 创新事业部的 HappyOyster 正式开放内测[1]。这不是一款普通的产品升级——它把"建造一个世界"这件事,第一次放进了普通创作者的能力范围[2] [3]。一个根本性的问题随之浮现:如果每一个创作者都能建造自己的世界&…...

Claude Design 来了:设计师的第二双手还是替代者?

2026年4月17日,Anthropic 正式发布 Claude Design。官方的定义是:一款通过与 Claude 对话来创建设计、原型、幻灯片、单页的工具。翻译成人话就是——你说话,它出图;你说「再瘦一点」「换个莫兰迪色系」「按钮往左挪」&#xff0c…...

为什么92%的“智慧交通”项目三年后停摆?AGI时代城市治理的3大认知断层与破局公式(内部推演纪要)

第一章:AGI驱动的城市交通治理范式革命 2026奇点智能技术大会(https://ml-summit.org) 传统交通治理长期受限于静态模型、滞后响应与孤岛式数据协同,而具备自主推理、多源语义理解与跨域决策能力的通用人工智能(AGI)正从根本上重…...

AGI推理延迟压至8.3ms?揭秘2026奇点大会上3家头部厂商联合发布的异构硬件栈,性能提升417%

第一章:2026奇点智能技术大会:AGI与硬件设计 2026奇点智能技术大会(https://ml-summit.org) AGI架构对芯片微架构的倒逼演进 本届大会首次披露了基于全栈可微分计算范式的AGI参考模型——Singularity-7B,其训练阶段要求硬件具备动态稀疏张量…...

AGI与量子计算融合的7个致命断层:2026奇点大会未公开技术白皮书首曝

第一章:AGI与量子计算融合的范式危机与奇点临界态 2026奇点智能技术大会(https://ml-summit.org) 当通用人工智能(AGI)的推理架构遭遇量子叠加态的本征坍缩机制,传统冯诺依曼—图灵范式正经历不可逆的结构性失稳。实验表明&#…...

使用Jmeter对接口进行压力测试

今天第一次使用Jmeter对系统进行了压力测试,测试了一下纯数据库方案以及添加了缓存的方案,结果惊人。只使用MySQL处理请求在设置并发量为每秒1000次的时候,可以看到MySQL的处理速度已经很慢了,平均响应时间达到了5235ms使用Caffei…...

Sunshine游戏串流终极指南:从零开始搭建自托管游戏主机

Sunshine游戏串流终极指南:从零开始搭建自托管游戏主机 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 想要在任何设备上流畅玩PC游戏,但厌倦了云游戏服务的…...