模块 05查看课程目录
00起跑线:两门语言,一台机器01先建立 BEAM 心智模型02Elixir 基础:让数据流过函数03Erlang 基础:读懂 BEAM 的母语04两种语法,一套语义05从裸进程理解并发06从手写循环推导 OTP07监督树与应用08状态、吞吐与背压09分布式与可运维性10Erlang ↔ Elixir 互操作11综合项目:可靠任务调度器
05
并发中级ElixirErlangBEAM

从裸进程理解并发

先亲手写消息循环,才知道 GenServer 替你处理了什么。

4检查点
6 小时预计完成
为什么先学这个

先修正心智模型,再增加 API

直接从 GenServer 开始,容易把 callback 当作框架魔法。裸进程暴露了关键事实:call 只是带引用的消息与等待回复;状态只是循环参数;超时、崩溃和陈旧回复都必须进入协议设计。

学完你能做到

可验证的学习目标

  • 能设计带唯一引用的 request/reply 协议
  • 能解释 link 与 monitor 的不同故障语义
  • 能识别同步死锁、陈旧回复与 mailbox 堆积
前置知识
  • 掌握两种语言的模式匹配
  • 理解 BEAM mailbox
最小心智模型

先抓住三个词

01

reference

VM 生成的高概率唯一值,常用于把某个 reply 与对应 request 配对。

02

link

双向故障关系。默认情况下,一个非 normal exit 会沿 link 传播。

03

monitor

单向观察关系。被观察进程退出时,观察者收到 `DOWN` 消息而不会自动退出。

双语代码桥

先对齐协议,再看标点

唯一引用避免把旧回复当成新请求的结果;timeout 只停止等待,并不会撤回已经发送的消息。

Elixir
def call(server, request, timeout \\ 1_000) do
  ref = make_ref()
  send(server, {:call, self(), ref, request})

  receive do
    {:reply, ^ref, response} -> {:ok, response}
  after
    timeout -> {:error, :timeout}
  end
end
Erlang
call(Server, Request, Timeout) ->
  Ref = make_ref(),
  Server ! {call, self(), Ref, Request},
  receive
    {reply, Ref, Response} -> {ok, Response}
  after Timeout ->
    {error, timeout}
  end.
LAB
可运行实验

制造一条过期回复

约 15–25 分钟

让服务器睡眠 1500ms,客户端 500ms 超时。随后检查客户端 mailbox:你会看到超时之后到达的 reply。

  1. 01

    实现一个收到请求后延迟回复的 server

  2. 02

    以 500ms timeout 发起 call

  3. 03

    等待两秒后运行 `Process.info(self(), :messages)`

在终端 / shell 中运行
Process.info(self(), :messages)
预期观察
  • call 返回 `{:error, :timeout}`
  • 迟到的 reply 仍可能出现在调用者 mailbox
故意弄坏

删除 ref,只按 `{:reply, response}` 匹配。连续发送两个不同延迟的请求,观察回复如何可能错配。

这个实验能证明

客户端超时与服务端工作取消是两件不同的事。

这个实验不能证明

一次错配演示不能覆盖所有调度顺序,也不能证明固定 timeout 适合生产流量。

快速自测

客户端 timeout 后,已经发给服务端的消息会怎样?

本章挑战

手写可靠 KV 进程

实现 get/put/delete,所有同步请求带 ref,支持 timeout;再提供 monitor 版本让调用者能区分超时与服务端崩溃。

提示 1轻推一下

先写消息协议,再写 loop。

提示 2缩小问题

把 `DOWN` 与 reply 放进同一个 receive。

提示 3接近实现

思考 monitor 在正常回复后何时 demonitor。

提示 4用验收标准反推

从下面每一条验收标准倒推一个最小测试。若某条无法写成测试,先把表述改成可观察结果。

完成标准
  • 并发请求不会因回复顺序不同而错配
  • 调用方能区分 timeout 与服务端退出
  • 测试覆盖迟到回复
带走这三句话

复习卡

  1. 1timeout 不是取消。
  2. 2reference 是 request/reply 配对的核心工具。
  3. 3link 用于共同生死,monitor 用于观察并做决定。
继续核对

本章一手资料

ProcessErlang concurrent programming