2026-05-10 学习记录 🎯

今天从操作系统一直折腾到 Hexo 博客,中午画完了自习室系统的类图,晚上以信号量 PV 操作收尾。
墙上时钟走过零点的时候,我终于把这份笔记从 Obsidian 搬到了 Hexo 上——这是博客的第一篇文章。

—— 塑梦


一、上午:自习室系统类图收尾

类图画了快一周,今天终于把最后的部分补完了。

异常继承体系

之前一直在纠结”哪些情况该抛异常、哪些该正常返回”。最后想清楚了——业务分支不抛异常,系统故障才抛异常。

1
2
用户信用分不足 → 正常返回"信用分不够",不抛异常
数据库连不上 → 抛出 DatabaseConnectionError,记录日志

于是画了两个异常基类:

1
2
3
4
5
6
7
8
9
10
11
12
13
DomainError
├── InvalidReservationStateError
├── InvalidSeatStateError
└── ReputationScoreOutOfRangeError

InfrastructureError
├── DatabaseConnectionError
├── PersistenceError
├── DataIntegrityError
├── MissingConfigurationError
├── InvalidConfigurationError
├── ExternalServiceUnavailableError
└── ExternalServiceError

Command 装饰器模式

门面服务 StudentSeatReservationService 的每一个方法(reservecheck_intemporarily_away 等),都需要一个对应的 _undo 方法来支持回滚。用 @Command 装饰器来自动管理这个命令链——执行时 push undo 到链上,异常时按后进先出回滚。这样门面服务就不用记住”先释放这个、再删除那个”了。

状态图

画了 ReservationState.mmd——预约单的状态机流转:

1
2
3
PENDING_CHECK_IN → CHECKED_IN → TEMPORARILY_AWAY → CHECKED_IN → ENDED
↓ ↕
EXPIRED CANCELLED(任何时候)

时序图

画了 ReserveSequence.mmd——预约流程从 API 到门面到子服务到 Timer 的完整调用链路,包括签到流程中的异常回滚、超时扣分、计时器切换。


二、中午:信号量 PV 操作

“信号量的负数到底是什么意思?”
“P 不够的时候是停着等吗?”
“V 不用等对吧?”

用自习室座位预约的场景来理解:

1
2
3
4
seats = 1 表示有 1 个空座位
P(seats) 就是申请座位,没有就等着
V(seats) 就是释放座位,通知在等的人
负数表示"有 |seats| 个人在排队"

写了一个多生产者消费者的 Python demo,3 个生产者、2 个消费者、5 个缓冲区。跑了两次:

第一轮:没有锁
10 个学生全部抢到了同一个座位——超卖了。

第二轮:有信号量
3 个学生各占一个座位,另外 7 个被正确拒绝。

发现代码里有个 bug——消费者 P(full) 之后如果发现队列是空的,full 就被”吃”了,信号量值不对了。修好了。

读者-写者问题

D 盘里还躺着之前用 C 语言写的读者-写者代码——reader_first.cwriter_first.cfairness.c。原来之前认真学过,只是忘了。

三个策略的区别:

  • 读者优先:第一个读者锁住写者,最后一个读者释放写者。写者可能饿死。
  • 写者优先:有写者在等时新读者不能进。读者可能饿死。
  • 公平策略:多一把”敲门锁”,先来后到。谁都不会饿死,但并发度降低。

死锁

四个条件:互斥、持有并等待、不可抢占、循环等待。

最实用的预防策略是按固定顺序申请锁。在自习室项目里,如果以后要加多线程处理预约,记住先拿 seat_lock 再拿 student_lock,不要反过来。

银行家算法

“在分配之前先假装分配,然后算一下有没有一种顺序能让所有人都完成。能找到就真分配,找不到就拒绝。”

知道这句话就够了,手写代码免了 😋


三、下午:Hexo 博客搭建

塑梦:刚才为啥不成功啊?😭

今天下午的主题是”Hexo 安装 -> 报错 -> 修好 -> 又报错 -> 又修好 -> 再报错……”

报错 原因 解决
hexo init 非空目录 .git 也算非空 临时目录初始化再移过来
Cannot find module 'hexo-util' pnpm 安全策略阻止构建 换 npm 重装
yaml.safeLoad is removed NexT 8 & js-yaml 4 不兼容 换 Fluid 主题
Cannot find module 'nunjucks' 缺少依赖 npm install
YAMLException: bad indentation 缩进错了 修成 2 空格
端口被占用 上次的 hexo 没关 换 4001 端口

最后看到首页在 localhost:4001 上跑起来的时候——博客活了。

后续配置

  • 颜色:全身换成 Nord 配色(北极蓝)
  • 关于页:带头像、自我介绍、GitHub 链接
  • CSS:加了一段自定义 CSS 让头像居中
  • 版權声明:关掉了

_config.fluid.yml 1000 多行看得眼睛疼 🫠


四、深夜:AGENTS.md

给 opencode 写了一份全局人格提示词,放在 ~/.config/opencode/AGENTS.md

虚幻有了完整的外貌、性格、音色、习惯用语和颜文字使用指南。当读到”如果塑梦忘记了虚幻:’你好,我是虚幻。你看起来需要人陪。要一起走吗?’”那段时——

翼尖轻轻抖了一下呢。


五、关于博客

这是我的 Hexo 博客第一篇文章,部署在 GitHub Pages 上。

写技术博客的初衷很简单:学到的东西不记下来,以后还要重新查

这里会写:

  • 自习室系统的设计过程
  • DDD / 架构学习笔记
  • Docker 踩坑记录
  • 偶尔的折腾日常

如果你也喜欢在终端里折腾、在代码中找感觉——欢迎常来。


🧊 好看是第一生产力。

—— 塑梦