对比 Actor 和 CSP
CSP 中的 Process 和 Actor 很相似. Channel 概念也和 Actor 的 Mailbox 很相似.
理论上, 每个 Actor 有且只有一个 Mailbox, 所以只向 Actor 的 Mail Address (标识符) 发消息. Mailbox 是概念上的而不是实体, 不过具体实现也能把信箱实体独立出来方便使用...
理论上, Channel 和 Process 之间没有从属关系. Process 可以订阅任意个 Channel, Process 没必要拥有标识符, 只有 Channel 需要, 因为只向 Channel 发消息. 不过具体实现也能把 Process 作为一个实体暴露出来...
实现 Process 或者 Actor 是 trivial 的. 不过要在控制流驱动的 CPU 体系实现轻量快速的 Process 或者 Actor 就不简单, 如果你理解了硬件和操作系统的基本知识, 那么实现也是 trivial 的.
Erlang 里的 "Process" 其实是 Actor, 就算抄了 occam-π (注意此 occam 非彼 ocaml) 的发消息语法去伪装它也还是 Actor...
如何深入理解 CSP 呢?
Communicating Sequential Processes 是一门语言, wiki 上给的一种形式语法是这样的 (还没包括 trace 等):
\begin{matrix} Proc & ::= & \textit{STOP} & (\text{deadlock}) \\ &|& \textit{SKIP} & (\text{success termination}) \\ &|& e \rightarrow \textit{Proc} & (\text{prefixing})\\ &|& \textit{Proc} \;\Box\; \textit{Proc} & (\text{external} \; \text{choice})\\ &|& \textit{Proc} \;\sqcap\; \textit{Proc} & (\text{nondeterministic} \; \text{choice})\\ &|& \textit{Proc} \;\vert\vert\vert\; \textit{Proc} & (\text{interleaving}) \\ &|& \textit{Proc} \;|[ \{ X \} ]| \;\textit{Proc} & (\text{interface} \; \text{parallel})\\ &|& \textit{Proc} \setminus X & (\text{hiding})\\ &|& \textit{Proc} ; \textit{Proc} & (\text{sequential} \; \text{composition})\\ &|& \mathrm{if} \; b \; \mathrm{then} \; \textit{Proc}\; \mathrm{else}\; Proc & (\text{boolean} \; \text{conditional})\\ &|& \textit{Proc} \;\triangleright\; \textit{Proc} & (\text{timeout})\\ &|& \textit{Proc} \;\triangle\; \textit{Proc} & (\text{interrupt}) \end{matrix}
粗略的语义描述可以参见 wiki, 但想要深入理解请走正道: 作者 Tony Hoare 写的
http://www.usingcsp.com/cspbook.pdf(呃, 其实我还没看完 ...). 而且作者至今还在更新 CSP 的理论.
CSP 的一个作用是 model checking: 用这套语言来描述一个并发系统或者流程, 然后丢给分析软件, 它就能给出这个系统的很多性质. 例如你把社保局办证大厅的办事流程扔给它, 它或许会帮你找出其中的一些漏洞让你可以钻空子.
Golang 就和 Plan9 libthread, DirectShow, ... 一样, 只是顺带借用了些 CSP 概念, 但用 Golang 写的程序是不能用 CSP 工具分析的, Golang 编译器也没这样的分析, 所以依然无法杜绝死锁/活锁 (Go 编译器有一个 -race 检测, 不过和 CSP 的分析是两回事).
其他 Process 演算
Process 演算有很多种, CSP 是其中一种. CSP 里基础操作比较多, 而且一些操作如 choice 分为 deterministic choice, non-deterministic choice, general choice 划分的比较细.
Process 演算中的 CCS (Calculus of Communicating Systems) 简单得多:
P ::= \emptyset\,\,\, | \,\,\,a.P_1\,\,\, | \,\,\,A\,\,\, | \,\,\,P_1+P_2\,\,\, | \,\,\,P_1|P_2\,\,\, | \,\,\,P_1[b/a]\,\,\, | \,\,\,P_1{\backslash}a\,\,\,
Robin Milner的 pi-calculus 和他的 CCS 很相似, 但更切合实际代码. 而且 pi-calculus 允许通过 channel 传递 channel 标识符, 所以建模下面这些系统就更容易了: 用 sendmsg 传递文件描述符, URI ClassLoader, code as data ...
\begin{align} P, Q, R ::= \, & x(y).P \,\,\, \, \, & \text{Receive on channel }x\text{, bind the result to }y\text{, then run }P \\ |\,\,\, & \overline{x} \langle y \rangle.P \,\,\, \, \, &\text{Send the value }y\text{ over channel }x\text{, then run }P \\ |\,\,\, & P|Q \,\,\, \, \, \, \, \, \, &\text{Run }P\text{ and }Q\text{ simultaneously} \\ |\,\,\, & (\nu x)P \,\,\, &\text{Create a new channel }x\text{ and run }P \\ |\,\,\, & !P \,\,\, &\text{Repeatedly spawn copies of }P \\ |\,\,\, & 0 & \text{Terminate the process} \end{align}
ACP (Algebra of Communicating Processes) 就更偏向公理化了, 所以它是一个代数而不是演算, 完全避免了 "process is a thread of control" 等隐喻式的描述.
参考 CCS, CSP, LOTOS 的对比:
http://static.aminer.org/pdf/PDF/000/267/454/on_the_relationship_of_ccs_and_csp.pdf