Effect 深度课effect@4.1.4 · LTS
流、调度与工程化

L23 并发原语与 STM

⏱ 30 min难度 3/5前置:L20
本课目标
  • 知道常见并发原语的用途
  • 理解事务内存解决什么问题
前置课时尚未完成:L20

可以自行跳转学习,但按顺序推进会更省力;学情分析会把这类缺口归入「前置缺口」。

常用原语

  • Ref:单个可变引用的原子读写(Ref.make / Ref.get / Ref.update)。
  • Deferred:一次性结果的占位,多方等待、一方完成(Deferred.await)。
  • Queue / PubSub:有界/无界队列与发布订阅,自带背压与中断语义。
  • Semaphore / Latch:许可控制与一次性门闩,用于限流与同步。
  • SubscriptionRef:可读变化流的状态引用,Stream.tap 能观察每次变更。
Ref 的基本用法
← 代码可左右滑动 →
import { Effect, Ref } from "effect"

const counter = Effect.gen(function* () {
  const ref = yield* Ref.make(0)
  yield* Effect.all(
    Array.from({ length: 10 }, () => Ref.update(ref, (n) => n + 1)),
    { concurrency: "unbounded" }
  )
  return yield* Ref.get(ref)
})
💡 v4 中 Ref 不是 Effect:要用 Ref.get / Ref.update,而不是直接 yield* ref。
🔬 STM:把多步状态变更变成一个事务

当多个引用必须「要么一起变、要么都不变」时,锁容易写错。v4 引入软件事务内存(Effect.tx 与 TxRef / TxQueue / TxHashMap / TxPubSub / TxSemaphore 等),把一组读写包成原子事务:冲突时由运行时重试,而不是由程序员手写锁与回滚。

交互演练
关键术语
Ref
fiber 安全的单值可变引用
STM
软件事务内存:一组读写作为原子事务执行
常见误区
× 用模块级 let 变量在并发 fiber 间共享状态,绕开原子性保证。
随堂测验(即时反馈,答题计入掌握度)
Q1v4 中想读一个 Ref 的值,正确写法是?
Q2STM 主要解决?