并发编程锁的10个高频陷阱:从加锁失效到死锁与性能优化
并发编程里的锁从来不是“加了synchronized就万事大吉”这么简单。这些年我做代码评审和线上问题排查见过太多锁相关的离奇事故有人明明加了锁数据照样错乱有人用Integer做锁锁到最后发现每个线程拿的居然是不同对象还有人把锁嵌套得挺漂亮结果服务毫无征兆地“卡死”一查线程dump全是DeadLock。这篇文章就把我从实际项目中归纳出来的 10 个高频场景一次性讲清楚按“加锁失效、可见性与原子性、死锁与活锁、性能陷阱”四个方向展开每个案例都给出错误写法、错误原因和修正方案。适合正在写业务并发代码的后端研发也适合准备面试时系统盘点锁机制的 Java 工程师。1. 加锁失效为什么你的 synchronized 完全没起作用加锁失效是最隐蔽的一类问题。表面上代码写的是synchronized语法也完全正确但运行时锁的根本不是同一个对象于是多个线程长驱直入共享数据稀里哗啦地错乱还不容易复现。这类问题通常在低并发下看不出来一旦压测或线上流量上来问题就爆了。1.1 案例 1用 Integer 当锁锁对象自己“跑”了很多代码喜欢用Integer当锁因为它写起来简洁。比如下面这个计数器public class IntegerLockDemo { private static Integer count 0; public static void increment() { synchronized (count) { count; } } }这段代码坑就坑在count这一步。Integer是不可变对象count在字节码层面会拆箱、自增、再装箱装箱过程会调用Integer.valueOf(int)它返回的可能是一个全新对象。也就是说当前线程在synchronized (count)里修改了count的引用下一个线程进来的时候锁的对象已经不是同一个了两个线程各自锁了不同的对象互斥自然失效。这类用法我实际排查过现象是“偶发少计数”代码怎么看都对就是结果不对。修复方案很简单锁对象永远用独立的、不会被重新赋值的final对象计数则交给AtomicInteger。public class IntegerLockDemoFix { private static final Object LOCK new Object(); private static int count 0; public static void increment() { synchronized (LOCK) { count; } } }经验凡是基本类型包装类、字符串等不可变对象都不要拿来当锁。锁对象必须是稳定存在的引用变量本身可以被重新赋值的话锁就跟着飘走了。1.2 案例 2synchronized(this)每个实例一把锁还有一个高频写法是直接锁this但因为线程使用的任务对象不一样锁形同虚设。public class Task implements Runnable { private int count 0; Override public void run() { synchronized (this) { count; System.out.println(count); } } } // 调用处 for (int i 0; i 10; i) { new Thread(new Task()).start(); }这段代码的问题在于每次new Task()Runnable实例都不一样synchronized (this)锁的自然是不同对象。10 个线程同时在各自的this上等待互不干扰count照样并发自增结果毫无秩序。这种错误在“每次都new对象丢给线程池”的代码里特别常见。修正方向有两个要么所有线程共享同一个Task实例要么干脆锁一个全局静态锁对象。Task task new Task(); for (int i 0; i 10; i) { new Thread(task).start(); }如果把逻辑改为共享一个任务实例锁this才有效。更稳妥的做法是直接用synchronized (Task.class)锁类对象或者定义private static final Object LOCK new Object()。需要记住的是锁对象是谁取决于所有线程访问的是不是同一个引用。1.3 案例 3字符串常量池当锁锁到别人家门口用字符串当锁是一个更隐蔽的坑。字符串字面量在 JVM 里有常量池复用机制也就是说你用lock这个字符串做锁哪怕是在完全不相干的类里只要都写synchronized (lock)它们锁的就是同一个对象。public class LockServiceA { public void methodA() { synchronized (LOCK) { // 业务逻辑 } } } public class LockServiceB { public void methodB() { synchronized (LOCK) { // 完全不相关的业务逻辑 } } }表面上看methodA和methodB风马牛不相及但因为共用同一个字符串对象这两段互不相干的代码会被迫串行执行。一个线程占住锁另一个业务模块的线程只能干等性能莫名其妙地下降。反过来如果两个方法本应互斥却因为其中一个用new String(LOCK)、另一个用字面量它们锁的又不是同一对象互斥失效。所以在真实项目里我从不建议用字符串做锁。锁对象要么是专用的static final Object要么是业务对象本身而不是字符串常量这种“全局可见”的东西。1.4 案例 4静态锁和实例锁两把不同的锁还有一种混合锁错误常见存在于工具类或者带静态方法的服务类里。比如这样public class Counter { private static int count 0; public synchronized void add() { count; } public static synchronized void staticAdd() { count; } }这里add()是实例方法锁的是thisstaticAdd()是静态方法锁的是Counter.class。两个线程一个调add()另一个调staticAdd()它们各自拿的是不同的锁对象共同操作同一个静态变量count数据安全照样无法保证。我见过有人把这种代码混在业务里本地自测没问题因为并发量不高一上生产就出现偶发数据错乱。修复的关键是统一锁对象如果目标共享数据是静态的那所有方法都应该用synchronized (Counter.class)或者private static final Object LOCK不要一半锁类、一半锁实例。排查加锁失效时有一个快速判断心法连续问自己三次“这个锁对象是同一个引用吗”。只要有一个环节是不确定的就要把锁对象改成显式的final对象。2. 可见性与原子性锁不彻底等于没写第二类问题比单纯的加锁失效更上一层锁确实生效了但因为用错了同步机制、或者在错误的阶段使用锁导致数据还是出问题。这一章里的案例集中在volatile误用、双重检查锁和复合操作不整体加锁。2.1 案例 5volatile 保证可见性但不保证原子性volatile是并发编程里最容易被误解的关键字之一。很多初学者以为变量加了volatile就线程安全了于是写出这样的计数逻辑public class VolatileCounter { private volatile int count 0; public void increment() { count; } }count实际上由三步组成读取 count、count 加 1、写回 count。volatile只能保证读和写对线程的可见性不能保证“先读后写”这个整体过程是原子的。两个线程可能同时读到同一个旧值各自加 1 后写回最终结果只增加了 1而不是 2。我早年压测一个统计接口时遇到过跑完 100 万请求统计值只有 80 多万当时排查了很久才发现是这个原因。要修复计数类需求用AtomicInteger的incrementAndGet()或者用synchronized包住整个自增操作。public class AtomicCounter { private AtomicInteger count new AtomicInteger(0); public void increment() { count.incrementAndGet(); } }理解volatile的最佳类比是它像一个公告栏所有人能看到最新公告但“看清公告、做出判断、修改公告”这个动作本身没有约束该打架还是打架。2.2 案例 6双重检查锁单例指令重排的暗坑双重检查锁是面试高频题也是实际代码里最容易“看起来对、用起来错”的写法。先看经典的错误版本public class Singleton { private static Singleton instance; public static Singleton getInstance() { if (instance null) { synchronized (Singleton.class) { if (instance null) { instance new Singleton(); } } } return instance; } }问题出在instance new Singleton()不是一个原子操作。它在 JVM 层面大致分为三步分配内存、调用构造器初始化对象、把引用指向内存。Java 允许指令重排序第三步可能先于第二步执行。这时另一个线程进来发现instance ! null直接返回了一个“还没初始化完的对象”后续使用就可能爆炸。修复方式是在instance字段上加上volatile从 JDK 5 之后volatile提供了完整的 happens-before 语义可以禁止这种重排序public class Singleton { private static volatile Singleton instance; public static Singleton getInstance() { if (instance null) { synchronized (Singleton.class) { if (instance null) { instance new Singleton(); } } } return instance; } }如果不想纠结双重检查锁的细节更省心的方案是使用静态内部类的懒加载方式或者直接使用枚举单例。它们由 JVM 的类加载机制保证线程安全代码也更简洁。2.3 案例 7复合操作拆开加锁等于没加还有一种非常典型的原子性问题锁加了但只加在了其中一段上整体流程还是有缝隙。比如这样一个本地缓存的重复加载问题public class CacheDemo { private MapString, String cache new HashMap(); public String get(String key) { if (!cache.containsKey(key)) { synchronized (this) { cache.put(key, loadFromDb(key)); } } return cache.get(key); } }这里containsKey判断在锁外面两个线程可能同时通过判断然后串行地进入锁各自执行了一次loadFromDb把数据库打了两遍。更严重的是如果锁内没有再次判断后一个线程可能会覆盖前一个线程写入的数据。正确做法是整个“检查然后写入”的复合操作必须处在同一把锁的保护下锁内还要再做一次二次判断public String get(String key) { synchronized (this) { if (!cache.containsKey(key)) { cache.put(key, loadFromDb(key)); } return cache.get(key); } }日常开发里这个错误太常见了因为它不是必现的只有在两个请求恰好同时到达的时序下才出问题。而“恰好同时到达”在高并发环境下只是时间问题。要规避这类复杂度现代开发更推荐直接使用ConcurrentHashMap的computeIfAbsent它把原子性封装好了不需要自己处理锁粒度。3. 死锁与活锁线程之间如何“锁死”前两章的问题大多是数据错乱这一章的问题更可怕线程直接不干活了服务整体卡死。死锁的经典场景是多个线程互相持有对方需要的锁形成循环等待。这里我整理三个实际项目中遇到的高频案例。3.1 案例 8账户转账嵌套锁交叉等待直接 DeadLock转账场景是说明死锁的经典例子。两个账户互相转账时如果锁嵌套顺序不一致就会出现僵局public class Transfer { public void transfer(Account from, Account to, int amount) { synchronized (from) { synchronized (to) { from.setBalance(from.getBalance() - amount); to.setBalance(to.getBalance() amount); } } } }线程 1 执行transfer(A, B, 100)先锁住 A线程 2 执行transfer(B, A, 100)先锁住 B。线程 1 想继续锁 B但 B 在线程 2 手里线程 2 想继续锁 A但 A 在线程 1 手里。两边都在等对方释放锁于是永久卡死。这不是理论推演我在一个模拟资金归集系统里压测时真的遇到过现场表现就是交易量跌到 0线程池全被占满。解决死锁的思路很多最实用的是“全局顺序加锁”。无论转账方向是什么都先锁 id 小的账户public void transfer(Account from, Account to, int amount) { Account first from.getId() to.getId() ? from : to; Account second from.getId() to.getId() ? to : from; synchronized (first) { synchronized (second) { // 转账逻辑 } } }这样所有线程都按同一个顺序拿锁就不会形成循环等待。另一种思路是使用tryLock带超时拿不到锁就释放已持有的锁避免死等。3.2 案例 9ReentrantLock 死等只会 lock() 不会 tryLock()很多从synchronized迁移到ReentrantLock的代码仍然习惯先lock()再干活。这种写法一旦遇到异常或持锁时间过长就会让其他线程无限期等待Lock lock new ReentrantLock(); public void doSomething() { lock.lock(); try { // 业务逻辑可能执行很久 } finally { lock.unlock(); } }表面看加了解锁没问题。但假如持锁线程因为外部接口超时卡住了 5 分钟其他线程就会在lock()这行排长队最终线程池耗尽、服务假死。synchronized拿不到锁也会等但ReentrantLock的优势就是可以带超时主动放弃。我更推荐在非绝对必要的情况下使用带超时的获取方式if (lock.tryLock(3, TimeUnit.SECONDS)) { try { // 业务逻辑 } finally { lock.unlock(); } } else { // 拿不到锁的兜底逻辑比如降级、回报失败 }tryLock起码给你留了一条“不无限等待”的后路。这不是说lock()不能用而是在不确定持锁时间的外部调用场景里超时机制能有效避免系统雪崩。3.3 案例 10读写锁升级读锁还没释放就要写锁ReentrantReadWriteLock是常见的读写分离工具但它的锁升级是一个雷区。所谓升级就是线程先持有读锁然后在持有读锁的情况下尝试获取写锁ReentrantReadWriteLock rwLock new ReentrantReadWriteLock(); public void updateCache() { rwLock.readLock().lock(); try { // 读取数据判断是否需要更新 rwLock.writeLock().lock(); // 这里会死锁 try { // 写入更新 } finally { rwLock.writeLock().unlock(); } } finally { rwLock.readLock().unlock(); } }读锁是共享锁可能被多个线程同时持有。当一个线程持有读锁想要升级为写锁时它必须等待所有读锁释放而它自己又占着一个读锁不放于是永远等不到自己释放形成自我死锁。我排查过类似问题线程dump里显示某一个线程在writeLock处等待而它就握着读锁非常典型的自锁。解决方式有两个方向如果需要“先读后写”那就先释放读锁再获取写锁但此时要处理中间其他线程抢先写的并发问题更好的选择是用StampedLock它支持tryConvertToWriteLock做锁升级的尝试或者干脆在明确可能要写的情况下直接用写锁。额外补充一个活锁的概念活锁并不是死锁它发生在两个线程在不断谦让、互相重试导致谁也做不成事。比如两个线程同时检测到冲突各自释放锁然后重试结果又同时冲突循环往复。解决活锁的办法通常是引入随机退避让两个线程下一次的节奏错开。4. 性能陷阱锁太重并发活活写成串行锁用对了不代表万事大吉。高并发场景下锁粒度就是决定系统吞吐量的关键因素。很多服务卡顿的原因并不是死锁而是锁的范围太大、竞争太激烈所有并发请求被迫排队吞吐量降了一个数量级。4.1 案例 11粗粒度锁让压测 QPS 断崖下跌这类问题最经典的表现是为了一段简单计算把一个方法的整个逻辑都塞进synchronized方法里。方法内部明明包含很多无共享状态的耗时操作比如远程调用、文件处理、序列化结果全部被锁串行化。public synchronized void process(Order order) { // 准备数据纯本地运算无共享变量 prepare(order); // 远程调用耗时较长 callRemoteService(order); // 更新共享状态真正需要锁的部分 updateSharedData(order); }process方法体里只有updateSharedData需要保护但粗粒度锁把callRemoteService这种高耗时、无共享的操作也锁住了。压测表现是 QPS 断崖下跌线程大部分时间阻塞在等待远程调用上CPU 利用率却很低。修正思路是缩小锁的范围把锁只放在真正需要保护的临界区上。远程调用和本地计算都挪到锁外。优秀实践里还会用“锁内只做必要的共享变量操作尽量不做 IO”这类原则。public void process(Order order) { prepare(order); callRemoteService(order); synchronized (this) { updateSharedData(order); } }4.2 什么时候从 synchronized 切换成 ReentrantLocksynchronized在现代 JVM 里已经很优化了有偏向锁、轻量级锁等演进绝大多数场景它是首选。但有些场景ReentrantLock的优势非常明显换锁能直接解决问题场景推荐选择原因简单互斥、代码短小synchronized使用简单JVM 自动释放锁需要超时获取锁ReentrantLocktryLock 带 TimeUnit需要响应中断ReentrantLocklockInterruptibly需要公平锁ReentrantLock构造器传入 true高并发读远多于写ReentrantReadWriteLock / StampedLock读锁共享不互斥我在实际项目里的习惯是能用synchronized就不用ReentrantLock因为它自带解锁语义不存在忘记释放的问题。只有出现明确诉求比如必须避免死等、必须做公平排队才切换到显式锁。4.3 用并发容器和无锁方案替代直接加锁很多时候最有效的“锁优化”是别用锁。JDK 提供了大量线程安全的容器和无锁工具覆盖了常见的并发场景。比如ConcurrentHashMap分段加锁适合高并发读写的 Map。CopyOnWriteArrayList读多写少场景写时复制。AtomicInteger、AtomicLong基于 CAS 的原子计数器。LongAdder极高并发计数场景比AtomicLong吞吐更高。BlockingQueue生产者消费者模型内部已处理好同步。内部使用 ThreadLocal把共享变量变成线程私有直接从根源消除竞争。我改造过一个统计模块原来用synchronized保护HashMap统计计数并发高时线程排队严重。后来换成ConcurrentHashMapLongAdderValue的组合压测吞吐率直接翻了几倍而且代码量还更少了。锁并不是越多越好“要不要锁、锁多大范围、能不能无锁”这三个问题永远值得在写代码前多想一遍。5. 避坑速查表与排查实战前面的案例覆盖了加锁失效、可见性、死锁、性能四类问题。这一章我压缩成可直接查阅的速查表再分享一些我常用的现场排查方法。5.1 十类案例速查对照场景关键词错误本质推荐修正Integer/Long 基本类型包装类做锁隐式拆装箱导致锁对象变化使用 final Object 独立锁对象每次 new Runnable 再锁 this锁的是不同实例共享实例或锁静态对象字符串字面量做锁字符串常量池导致全局偶合使用显式专用锁对象静态方法锁 Class实例方法锁 this两把锁互不重叠统一锁对象volatile 修饰自增变量可见性不等于原子性使用 AtomicInteger双重检查锁缺 volatile指令重排导致半初始化对象instance 加 volatile检查与写入拆开加锁复合操作存在窗口期整个复合操作放锁内多个锁嵌套且顺序不一致循环等待死锁按固定顺序加锁或 tryLocklock() 后无限等待没有超时机制tryLock 带超时兜底读写锁升级读锁未释放无法获取写锁释放读锁再拿写锁或 StampedLock这张表其实也是我自查清单的来源。遇到并发问题先对照表格看代码踩中了哪个如果没有直接命中再往下走排查流程。5.2 现场排查锁问题的操作流程线上出问题时最有效的第一步不是翻代码而是把现场保存下来。当服务卡死或线程池耗尽先用jstack拿到线程dumpjstack pid thread_dump.txt打开thread_dump.txt重点找以下几类关键信息Found one Java-level deadlockJVM 已经明确检测到死锁。waiting for monitor entry线程在等待 synchronized 锁。parking to wait for ... (a java.util.concurrent.locks.ReentrantLock...)线程在等待显式锁。BLOCKED状态线程数量是否过多如果大量线程 BLOCKED说明锁竞争太激烈。第二步是分析线程调用栈。假设发现多个线程互相持有不同的锁并等待对方基本可以确认死锁如果大量线程卡在同一个锁对象上则更像锁粒度问题需要回看代码缩小锁范围。第三步是用jcmd pid Thread.print或者 JDK 自带的jconsole做重复采样。死锁大概率是稳定复现的多抓几次线程状态就能确认是偶发还是持续。值得多提一句线上排查时不要急着重启服务先把dump和日志留下来否则问题重启之后就很难定位了。5.3 写锁之前的“三句自问”踩过足够多的坑之后我现在写任何锁代码之前都会默念一遍这三个问题第一问锁对象是所有线程共享的同一个引用吗只要不是同一个引用锁等于没加。第二问锁覆盖的范围包含全部共享变量操作了吗if判断加上后面的写操作必须整体在锁内不能留窗口。第三问多个锁嵌套时所有线程的加锁顺序一致吗顺序不一致就是死锁温床。这三个问题覆盖了加锁失效、复合操作原子性和死锁三大核心能过滤掉绝大部分并发 bug。代码写完提交评审前我还会专门跑一遍高并发自测用几十个线程同时操作共享数据观察是否出现数据错乱或线程卡住。并发问题的特点是概率极低但破坏极大自测阶段多花时间线上才能少熬夜。文章写到这里我再分享一个自己的观察。很多人学并发时盯着原理和 API 记真正到了项目里踩坑往往不是因为原理不懂而是因为写代码时没有形成“锁对象一致性”这类条件反射。比如Integer做锁、字符串做锁、静态实例锁混用这些错误背后不是不会用 synchronized而是没有在落笔瞬间意识到“锁的关键是锁谁”。如果你能把“锁的是谁、锁的范围、锁的顺序”这三点内化成习惯并发代码的质量会有明显提升。把这篇文章收藏起来写完锁相关代码后对着速查表过一遍比翻教科书高效得多。

相关新闻

Spring Boot+MyBatis中@Mapper扫不到?原理与排查思路一次讲透

Spring Boot+MyBatis中@Mapper扫不到?原理与排查思路一次讲透

前两天在群里看到有人贴报错:启动类能跑,但Service一注入Mapper的时候就挂,提示Consider defining a bean of type xxx.xxx.UserMapper in your configuration.点开代码,明明每个Mapper接口上都写了Mapper,标题也搜的“mybaties扫描不到mapper”。这个问题在Spring Boot MyBat…

2026/10/16 4:36:22 阅读更多 →
计算机网络体系结构:分层思想与TCP/IP模型核心考点精讲

计算机网络体系结构:分层思想与TCP/IP模型核心考点精讲

1. 为什么第一章要从“体系结构”开始很多同学刚开始复习计算机网络,翻到目录看到第一章是“计算机网络体系结构”,心里会嘀咕:这章看起来全是抽象概念,什么分层、协议、服务、接口,又不讲具体技术,是不是可…

2026/10/16 4:36:22 阅读更多 →
基于SSM框架的智能密室逃脱信息管理系统设计与实践

基于SSM框架的智能密室逃脱信息管理系统设计与实践

1. 项目概述1.1 一句话理解这个项目这是一个基于SSM框架(Spring SpringMVC MyBatis)开发的信息管理系统,业务场景切的是“智能密室逃脱”。它不是一个游戏引擎,也不做密室内的机关控制,而是管理密室逃脱门店的日常运…

2026/10/16 4:35:22 阅读更多 →

最新新闻

C++第二章:数据类型、表达式与流程控制常见陷阱解析

C++第二章:数据类型、表达式与流程控制常见陷阱解析

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

2026/10/16 5:21:34 阅读更多 →
基于PIC32与MP2642的两串电池主动均衡方案设计

基于PIC32与MP2642的两串电池主动均衡方案设计

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

2026/10/16 5:21:34 阅读更多 →
OpenCV Mat拷贝详解:浅拷贝与深拷贝的陷阱、区别及最佳实践

OpenCV Mat拷贝详解:浅拷贝与深拷贝的陷阱、区别及最佳实践

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

2026/10/16 5:21:34 阅读更多 →
RS485与Modbus主从拓扑选型:多主一从和一主多从的工程实践

RS485与Modbus主从拓扑选型:多主一从和一主多从的工程实践

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

2026/10/16 5:21:34 阅读更多 →
哈夫曼编码从原理到实现:前缀码判定与WPL最小性

哈夫曼编码从原理到实现:前缀码判定与WPL最小性

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

2026/10/16 5:21:34 阅读更多 →
中级数据库系统工程师备考:标准化与知识产权通关要点

中级数据库系统工程师备考:标准化与知识产权通关要点

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

2026/10/16 5:20:33 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

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

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/15 9:49:14 阅读更多 →