首页/新闻资讯/正文详情

Java并发编程05:互斥锁(下)-互斥锁保护多个资源

发布时间:2026/11/3 11:05:44 来源:云帆数科 栏目:资讯中心
Java并发编程05:互斥锁(下)-互斥锁保护多个资源
05、Java并发编程互斥锁下如何用一把锁保护多个资源一、痛点场景线上转账事故明明加了锁还是丢钱去年我在某支付核心系统值班凌晨三点告警突然炸了。业务方反馈用户 A 转给用户 B 100 元用户 B 转给用户 C 100 元跑完之后用户 B 的余额既不是预期的 200 元也不是多了或者少了 100而是直接变成了 300 元或者 100 元。钱凭空多了一笔又凭空消失了一笔财务对账系统直接亮红灯。开发同学拍着胸脯说“我 transfer 方法上加了synchronized关键字啊不可能有并发问题。”我们把日志拉出来一看问题就出在这把synchronized上。代码长这样classAccount{privateintbalance;synchronizedvoidtransfer(Accounttarget,intamt){if(this.balanceamt){this.balance-amt;target.balanceamt;}}}看起来非常正确临界区里同时操作了转出账户和转入账户还用synchronized把方法锁了。但问题在于这把synchronized锁的是this也就是当前调用 transfer 的那个对象实例。线程 1 执行 A 转 B锁住的是 A.this线程 2 执行 B 转 C锁住的是 B.this。两把不同的锁两个线程根本不互斥它们同时读到 B 的余额都是 200然后各自写回一个值最后 B 的余额就被覆盖了。这是一个真实发生在生产环境的事故也是 Java 并发面试中被问烂的一道题你以为你加了锁实际上你加了两把不同的锁。更要命的是这种 bug 在测试环境根本复现不出来。单线程跑、低并发跑都好好的一到生产高并发概率性出现查都查不到。等你查日志的时候钱已经对不上了。文章目录05、Java并发编程互斥锁下如何用一把锁保护多个资源一、痛点场景线上转账事故明明加了锁还是丢钱二、是什么一把锁保护多个资源的本质2.1 专业解释2.2 大白话翻译2.3 生活案例三、为什么需要区分无关联资源 vs 关联资源3.1 资源之间没有关联关系3.2 资源之间有关联关系3.3 专业解释为什么 this 锁不行3.4 大白话翻译3.5 生活案例四、演进过程从错误写法到正确姿势4.1 第一版错误this 锁4.2 第二版思路传入共享锁对象4.3 第三版正确Account.class 锁4.4 第四版进阶按顺序加锁避免死锁五、怎么用企业项目实战代码5.1 场景一简单转账中小项目5.2 场景二高并发转账生产级5.3 场景三保护无关联资源细粒度锁六、竞品对比synchronized vs ReentrantLock vs 其他方案6.1 专业解释6.2 大白话翻译6.3 生活案例七、常用场景总结7.1 什么时候用一把锁保护多个资源7.2 什么时候用细粒度锁多锁保护多资源7.3 企业项目中的最佳实践八、面试官高频面试题问题 1synchronized 修饰方法和修饰代码块有什么区别问题 2为什么 synchronized 修饰 transfer 方法还会出并发问题问题 3synchronized 和 ReentrantLock 的区别问题 4synchronized 的锁升级过程问题 5什么是 Account.class 锁为什么用它问题 6转账操作怎么避免死锁问题 7什么是细粒度锁什么是粗粒度锁问题 8synchronized 是公平锁还是非公平锁九、总结二、是什么一把锁保护多个资源的本质2.1 专业解释在并发编程中受保护资源和锁之间的合理关联关系是 N:1也就是一把锁可以保护多个资源但不能用多把锁去保护同一个资源。这个原则在上一篇文章里我们已经讲过这一篇重点讲N:1怎么落地。这里的N指的是多个受保护资源1指的是一把锁。关键在于这把锁必须能覆盖到所有需要被原子性保护的资源。2.2 大白话翻译你可以把锁理解成电影院的检票员把资源理解成座位。如果是一个座位对应一个检票员1:1那就是一把锁保护一个资源最简单。如果是整个影厅的座位只需要一个检票员N:1那就是一把锁保护多个资源。最蠢的做法是一个座位配一个检票员但检票员之间互相不认识结果两个人同时坐一个座位这就是多把锁保护一个资源必出问题。2.3 生活案例你家里有一个保险箱里面放了房产证、护照、户口本。这三样东西平时分开用你不需要把它们锁在三个不同的保险箱里——那样你开三次锁既慢又麻烦。你只需要一个保险箱、一把钥匙谁要用里面的东西谁就拿钥匙开开完放回去下一个人再用。这就是一把锁保护多个资源。但如果你的保险箱里放的是夫妻共同财产你老婆要用房产证办贷款你要用护照出国这两件事必须同时考虑那就不能各用各的锁了必须用同一把锁否则你俩一个拿了房产证出门一个拿了护照出门中间状态别人看到会以为家里被盗了。三、为什么需要区分无关联资源 vs 关联资源3.1 资源之间没有关联关系如果多个资源之间完全独立没有原子性要求那就应该用细粒度锁每个资源一把锁互不干扰。最典型的例子是账户类里的两个字段余额和密码。取款操作只动余额改密码只动密码这两件事半毛钱关系没有你完全可以让它们并行执行。classAccount{// 锁保护账户余额privatefinalObjectbalLocknewObject();privateIntegerbalance;// 锁保护账户密码privatefinalObjectpwLocknewObject();privateStringpassword;voidwithdraw(Integeramt){synchronized(balLock){if(this.balanceamt){this.balance-amt;}}}IntegergetBalance(){synchronized(balLock){returnbalance;}}voidupdatePassword(Stringpw){synchronized(pwLock){this.passwordpw;}}StringgetPassword(){synchronized(pwLock){returnpassword;}}}这里用了两把锁balLock和pwLock取款和改密码可以同时进行性能比用一把this锁好很多。这就是细粒度锁的价值能并行的地方尽量并行。3.2 资源之间有关联关系如果多个资源之间有一致性要求比如转账操作里 A 减钱和 B 加钱必须是一个原子操作那这两个资源就必须被同一把锁保护。问题在于this这把锁是对象级别的每个 Account 实例都有自己的 this。你锁了 A.this只能保护 A.balance保护不了 B.balance。3.3 专业解释为什么 this 锁不行synchronized修饰实例方法时锁对象是this也就是当前实例。每个 Account 对象在 JVM 堆里都是独立的实例各自有各自的对象头Mark Word各自持有自己的 Monitor。线程 1 调用 A.transfer(B, 100)进入同步块锁定 A 对象的 Monitor线程 2 调用 B.transfer(C, 100)进入同步块锁定 B 对象的 Monitor。两个 Monitor 是完全不同的对象JVM 认为这是两个不相关的临界区所以不会互斥。这就是问题根源。3.4 大白话翻译你家的门锁只能锁你家的门锁不了隔壁老王家的门。你拿自己家的钥匙去开老王家的保险柜当然打不开。但转账这个操作偏偏要求你同时锁住你家的保险柜和老王家的保险柜中间谁都不能动。3.5 生活案例公司年会上抽奖奖池里有一等奖、二等奖、三等奖。抽奖这个动作要同时做两件事从奖池里扣掉一个奖项往中奖者账户里加一个奖项。这两件事必须一起成功或者一起失败。如果你给一等奖池配一把锁、二等奖池配一把锁、中奖者账户配一把锁三个人同时抽奖一个人抽一等奖扣了奖池但还没加到中奖者另一个人正好读到这个中间状态就乱套了。正确做法是整个抽奖系统就一把大锁谁抽奖谁拿这把锁抽完放下下一个人再拿。四、演进过程从错误写法到正确姿势4.1 第一版错误this 锁就是开头那个事故代码synchronized修饰 transfer 方法。看起来对实际上锁的范围只覆盖了 this.balance没覆盖 target.balance。4.2 第二版思路传入共享锁对象既然每个实例自己的 this 不行那我们就让所有 Account 对象共享一把外部传进来的锁。classAccount{privateObjectlock;privateintbalance;privateAccount(){}publicAccount(Objectlock){this.locklock;}voidtransfer(Accounttarget,intamt){synchronized(lock){if(this.balanceamt){this.balance-amt;target.balanceamt;}}}}这个方案在原理上是对的只要创建 Account 时传入的是同一个 lock 对象所有实例就共享一把锁。但问题是它太依赖人工保证了。在真实项目里创建 Account 的代码可能分散在十几个工程、几十个类里你怎么保证每一处 new Account() 传的都是同一个 lock万一某个新人图省事 new 了一个新 lock 传进去立刻就回到第一版的 bug。4.3 第三版正确Account.class 锁JVM 加载类的时候会为每个类创建唯一的Class对象。Account.class这个对象在整个 JVM 里全局唯一所有 Account 实例天然共享它不需要你手动传。classAccount{privateintbalance;voidtransfer(Accounttarget,intamt){synchronized(Account.class){if(this.balanceamt){this.balance-amt;target.balanceamt;}}}}这就是最简洁、最可靠的写法。Account.class是类级别的锁所有 Account 实例共用不存在传错的问题。4.4 第四版进阶按顺序加锁避免死锁Account.class锁虽然解决了互斥问题但它是一个全局粗粒度锁所有转账操作都串行执行高并发下性能瓶颈明显。更重要的是如果你在一个方法里需要同时锁两个对象比如 A 转 B 和 B 转 A 同时发生用两把对象锁就会死锁。工业界更成熟的做法是给每个账户一个唯一 ID永远先锁 ID 小的账户再锁 ID 大的账户这样所有线程的加锁顺序一致不会循环等待。importjava.util.concurrent.locks.Lock;importjava.util.concurrent.locks.ReentrantLock;classAccount{privatefinalStringid;privateintbalance;privatefinalLocklocknewReentrantLock();publicAccount(Stringid,intbalance){this.idid;this.balancebalance;}publicvoidtransfer(Accounttarget,intamt){Accountfirstthis.id.compareTo(target.id)0?this:target;Accountsecondfirstthis?target:this;first.lock.lock();try{second.lock.lock();try{if(this.balanceamt){this.balance-amt;target.balanceamt;}}finally{second.lock.unlock();}}finally{first.lock.unlock();}}}这个方案在 CodeSignal、剑桥大学并发课程里都有提到是银行转账系统的标准解法。它既避免了 this 锁保护不到 target 的问题又避免了 Account.class 全局串行的性能问题还避免了交叉加锁导致的死锁。五、怎么用企业项目实战代码5.1 场景一简单转账中小项目如果你的项目并发量不高用Account.class锁就够了简单粗暴不出错。publicclassAccount{privateStringaccountNo;privateintbalance;publicAccount(StringaccountNo,intbalance){this.accountNoaccountNo;this.balancebalance;}publicvoidtransfer(Accounttarget,intamt){synchronized(Account.class){if(this.balanceamt){thrownewIllegalArgumentException(余额不足);}this.balance-amt;target.balanceamt;System.out.printf([%s] - [%s] 转出 %d当前余额 %d目标余额 %d%n,this.accountNo,target.accountNo,amt,this.balance,target.balance);}}publicintgetBalance(){synchronized(Account.class){returnbalance;}}}测试代码publicclassTransferTest{publicstaticvoidmain(String[]args)throwsInterruptedException{AccountanewAccount(A,200);AccountbnewAccount(B,200);AccountcnewAccount(C,200);Threadt1newThread(()-a.transfer(b,100));Threadt2newThread(()-b.transfer(c,100));t1.start();t2.start();t1.join();t2.join();System.out.println(Aa.getBalance());System.out.println(Bb.getBalance());System.out.println(Cc.getBalance());}}正确输出一定是 A100, B200, C300。5.2 场景二高并发转账生产级核心支付系统不能用全局锁必须用按 ID 排序加锁的方案。完整代码见 4.4 节。这里补充一个带超时的版本防止某个线程卡住永久占用锁importjava.util.concurrent.locks.ReentrantLock;importjava.util.concurrent.TimeUnit;publicclassSafeAccount{privatefinalStringid;privateintbalance;privatefinalReentrantLocklocknewReentrantLock();publicSafeAccount(Stringid,intbalance){this.idid;this.balancebalance;}publicbooleantransfer(SafeAccounttarget,intamt,longtimeoutMs)throwsInterruptedException{SafeAccountfirstthis.id.compareTo(target.id)0?this:target;SafeAccountsecondfirstthis?target:this;if(!first.lock.tryLock(timeoutMs,TimeUnit.MILLISECONDS)){returnfalse;}try{if(!second.lock.tryLock(timeoutMs,TimeUnit.MILLISECONDS)){returnfalse;}try{if(this.balanceamt){returnfalse;}this.balance-amt;target.balanceamt;returntrue;}finally{second.lock.unlock();}}finally{first.lock.unlock();}}}tryLock带超时时间获取不到锁就快速失败不会让线程傻等这在生产环境非常重要。5.3 场景三保护无关联资源细粒度锁如果你的类里有多个独立字段不要图省事用一个this锁全包那样性能太差。应该给每个独立资源配一把专门的锁。importjava.util.concurrent.locks.ReentrantLock;publicclassBankAccount{privateintbalance;privateStringpassword;privatefinalObjectbalanceLocknewObject();privatefinalObjectpasswordLocknewObject();publicvoidwithdraw(intamt){synchronized(balanceLock){if(balanceamt){balance-amt;}}}publicvoidchangePassword(StringoldPwd,StringnewPwd){synchronized(passwordLock){if(oldPwd.equals(password)){passwordnewPwd;}}}}取款和改密码完全并行吞吐量直接翻倍。六、竞品对比synchronized vs ReentrantLock vs 其他方案这是面试必考的对比也是企业选型的核心依据。对比维度synchronizedReentrantLockAccount.class 锁实现方式JVM 关键字底层 monitorenter/monitorexitJDK API基于 AQSsynchronized 的一种用法锁释放自动释放出块或异常都释放必须手动 finally 释放忘了就死锁自动释放可重入是是是公平锁非公平可选公平/非公平非公平尝试获取锁不支持tryLock() 支持不支持可中断获取不支持lockInterruptibly() 支持不支持超时获取不支持tryLock(timeout) 支持不支持多条件变量只有一个 wait/notify多个 Condition只有一个锁粒度对象级/类级对象级灵活组合类级全局唯一性能JDK 6经过锁升级优化与 ReentrantLock 接近略好于 synchronized高并发下优势明显等同 synchronized适用场景简单互斥代码简洁需要高级功能超时、中断、多条件跨实例共享资源保护6.1 专业解释JDK 1.6 之前synchronized 是重量级锁性能比 ReentrantLock 差很多。JDK 1.6 引入了锁升级机制无锁 - 偏向锁 - 轻量级锁CAS 自旋- 重量级锁OS Mutex。竞争不激烈的时候走偏向锁和轻量级锁性能非常好只有竞争激烈、自旋超过阈值才升级到重量级锁。所以现在的结论是大部分场景 synchronized 就够了性能不差代码还简洁。只有当你需要 tryLock 超时、可中断、多 Condition、公平锁这些高级特性时才上 ReentrantLock。6.2 大白话翻译synchronized 就像自动挡汽车踩油门就走熄火自动拉手刹不用你操心ReentrantLock 就像手动挡离合、档位、手刹都得自己来但你能精确控制每一个动作。日常开自动挡够用了赛车比赛才需要手动挡。6.3 生活案例公司门禁卡synchronized 是公司大门的自动门人走到门口自动开出去自动关你不用管。ReentrantLock 是机房的手动门你得自己刷门禁、自己推门、出来的时候记得带上门忘了带门别人就能随便进。Account.class 锁是整栋大楼唯一一把万能钥匙不管你在几楼哪个房间要进去都得找物业拿这把钥匙。七、常用场景总结7.1 什么时候用一把锁保护多个资源银行转账转出账户和转入账户必须同时修改中间状态不可见。库存扣减下单时扣减商品库存和增加订单记录必须原子完成。资金对账主账户余额和子账户余额必须保持一致。配置热更新读配置和写配置必须互斥否则读到半新半旧的配置。单例模式双重检查锁定多个资源实例引用、状态标志要一起保护。缓存一致性缓存失效和数据库回源必须串行防止缓存击穿。7.2 什么时候用细粒度锁多锁保护多资源用户信息模块余额、密码、头像、昵称互不关联各用各的锁。日志系统不同文件的写入互不影响每个文件一把锁。连接池每个连接独立管理不需要全局锁。多队列消费者不同队列之间不竞争各锁各的。7.3 企业项目中的最佳实践优先用 synchronized简单场景不要上 ReentrantLock。跨实例共享资源优先考虑 Account.class 这种类级锁。多对象加锁必须按固定顺序比如 ID 排序防止死锁。高并发场景用 tryLock 带超时不要无限等待。锁的范围尽量小只包住真正需要原子性的代码不要把整个方法都锁了。锁对象用private final修饰防止外部篡改锁对象。八、面试官高频面试题问题 1synchronized 修饰方法和修饰代码块有什么区别答修饰实例方法时锁的是当前实例 this修饰静态方法时锁的是类对象 Class修饰代码块时锁的是括号里指定的对象。修饰代码块更灵活可以控制锁的粒度只包住需要互斥的代码段。问题 2为什么 synchronized 修饰 transfer 方法还会出并发问题答因为 synchronized 锁的是 this也就是当前调用方法的对象。转账操作涉及两个对象this 和 target。this 锁只能保护 this.balance保护不了 target.balance。两个线程分别操作不同的 Account 实例持有的是不同的 this 锁不会互斥。解决方法是用 Account.class 这种共享锁或者按顺序锁两个对象。问题 3synchronized 和 ReentrantLock 的区别答synchronized 是 JVM 关键字自动释放锁代码简洁ReentrantLock 是 JDK API必须手动 finally 释放但是支持 tryLock 超时、可中断获取、公平锁、多 Condition。JDK 1.6 之后 synchronized 经过锁升级优化性能差距不大简单场景用 synchronized需要高级功能用 ReentrantLock。问题 4synchronized 的锁升级过程答无锁状态 - 偏向锁同一个线程反复进入记录线程 ID- 轻量级锁多个线程交替进入CAS 自旋- 重量级锁竞争激烈自旋失败升级为 OS 级互斥量线程阻塞。锁升级是单向的不能降级。JDK 15 之后偏向锁被废弃。问题 5什么是 Account.class 锁为什么用它答Account.class 是 JVM 加载类时创建的唯一 Class 对象在整个 JVM 里全局唯一。所有 Account 实例都共享这把锁不需要手动传入。它解决的是this 锁只能保护当前实例保护不了其他实例的问题。缺点是锁粒度太粗所有操作全局串行高并发下性能差。问题 6转账操作怎么避免死锁答两个线程互相持有对方需要的锁就会死锁。解决方法是按固定顺序加锁给每个账户一个唯一 ID永远先锁 ID 小的账户再锁 ID 大的账户。这样所有线程加锁顺序一致不会循环等待。也可以用 tryLock 带超时获取不到就放弃重试。问题 7什么是细粒度锁什么是粗粒度锁答细粒度锁是每个资源配一把独立的锁不同资源之间可以并行性能好但管理复杂粗粒度锁是一把锁保护所有资源简单但所有操作串行性能差。原则是有关联的资源用一把粗粒度锁保护无关联的资源用细粒度锁分开保护。问题 8synchronized 是公平锁还是非公平锁答synchronized 只能是非公平锁。新线程有可能直接插队获取锁而不是等队列里的线程先拿。ReentrantLock 默认也是非公平但可以构造为公平锁。非公平锁吞吐量更高因为减少了线程切换开销。九、总结这篇文章我们讲了互斥锁保护多个资源的核心逻辑第一先判断资源之间有没有关联。没有关联的资源用细粒度锁分开保护能并行就并行有关联的资源必须用同一把锁保护保证操作的中间状态对外不可见。第二this 锁只能保护当前实例保护不了其他实例。跨实例的资源保护要用类级锁Account.class或者外部传入的共享锁对象。第三多对象加锁必须按固定顺序防止死锁。高并发场景用 tryLock 带超时不要无限等待。第四选型上简单场景用 synchronized 就够了JDK 1.6 之后性能已经很好需要超时、中断、多条件变量这些高级功能才上 ReentrantLock。最后记住一句话原子性的本质不是不可分割而是中间状态对外不可见。你加锁的目的就是让别人看不到你操作到一半的样子。本文为原创文章如需转载请联系作者获得授权并注明出处。

相关推荐

嵌入式系统工程落地指南:ARM/RISC-V平台开发Checklist
嵌入式系统工程落地指南:ARM/RISC-V平台开发Checklist

简介:这是一份面向嵌入式系统开发工程师的综合性技术指南,尤其适合具备一定硬件与软件基础、正参与实际项目开发或系统性进阶学习的研发人员。资源系统梳理了从硬件选型(ARM Cortex、RISC-V、STM32平台)、外设驱动(GPI… · 2026/11/3 11:05:44

高端书型礼盒包装制作全流程与工艺解析
高端书型礼盒包装制作全流程与工艺解析

1. 印刷书型礼盒包装全流程概述 书型礼盒作为高端包装的经典形式,在礼品、珠宝、奢侈品等行业应用广泛。与传统包装相比,它的开合方式类似书籍,既能保护内容物,又能通过精良的做工提升产品档次。我经手过上百个书型盒项目&#xf… · 2026/11/3 11:05:44

耕地后备资源调查技术总结报告:内容、方法与易混概念辨析
耕地后备资源调查技术总结报告:内容、方法与易混概念辨析

简介:这份耕地后备资源调查技术总结报告范文面向国土调查、土地规划与整理复垦领域的从业者及项目编制人员,提供可直接参考的技术总结报告框架与写作素材。报告围绕项目目标与内容、调查区地理位置与范围、技术路线、项目实施、质量保证及提交资料成果六… · 2026/11/3 11:04:40

SQL Server即时通讯数据查询实战:多表关联、索引优化与窗口函数
SQL Server即时通讯数据查询实战:多表关联、索引优化与窗口函数

1. 从一张“QQ查询”需求单说起:这个项目到底在做什么很多人第一次看到“数据库(SQL Server)QQ查询”这个标题,第一反应是“查QQ号?”,其实真正落到开发场景里,它指的是一套围绕即时通讯类业务数… · 2026/11/3 12:53:33

R语言试题自测:从基础漏洞到统计检验的实战验证
R语言试题自测:从基础漏洞到统计检验的实战验证

简介:面向R语言初学者与备考复习人群的试题练习文档,围绕基础统计概念与R语言入门操作展开,可用于课堂测验、自学自测与考前查漏补缺。内容覆盖描述性统计与推断性统计的区分、名义数据与计量数据等数据类型辨析,以及getwd()、hea… · 2026/11/3 12:53:33

HTML网页开发入门:从基础到实战
HTML网页开发入门:从基础到实战

1. HTML网页操作基础入门 HTML作为网页开发的基石语言,是每个想学习网页制作的新手必须掌握的第一课。记得我第一次接触HTML时,被那些尖括号和标签搞得晕头转向,但实际动手操作几次后才发现,它远比想象中简单有趣。下面我就从最基… · 2026/11/3 12:53:33

SkyWalking自定义告警指标与日志监控实战
SkyWalking自定义告警指标与日志监控实战

1. SkyWalking自定义告警指标深度解析 在分布式系统监控领域,SkyWalking作为一款优秀的APM工具,其告警功能一直是运维人员关注的焦点。传统告警配置往往局限于预设指标,而实际生产环境中,我们经常需要根据业务特性定制专属监控规则… · 2026/11/3 12:53:33

SQL Server实战:用QQ场景练透数据库查询与优化
SQL Server实战:用QQ场景练透数据库查询与优化

1. 从"QQ查询"这个标题说起:一个被低估的数据库实战切口 第一次看到"数据库(SQL Server)QQ查询"这个标题,很多人可能会愣一下——QQ和SQL Server有什么关系?其实这正是这个项目最有意思的地方。它… · 2026/11/3 12:53:33

协同管理软件核心解析:表单、流程、门户与空间分层
协同管理软件核心解析:表单、流程、门户与空间分层

简介:这份资源是致远互联A8协同管理软件V9.0集团版的官方用户操作手册,面向集团型企业管理者、信息化实施人员及日常办公用户,帮助其快速熟悉平台功能、完成客户端配置并掌握协同事项处理流程。手册围绕协同“九宫格”管理理念展开&#xff0… · 2026/11/3 12:52:22

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46

STM32F411RE与MAX14431实现SPI隔离:工业现场抗共模干扰实战
STM32F411RE与MAX14431实现SPI隔离:工业现场抗共模干扰实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59

ESP32+大模型AI硬件开发:从Demo到产品的8个工程问题
ESP32+大模型AI硬件开发:从Demo到产品的8个工程问题

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59

基于MAX14431BAEE+与PIC18F85J10的SPI隔离方案设计与实践
基于MAX14431BAEE+与PIC18F85J10的SPI隔离方案设计与实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码