我在第379页的专家F#副本中注意到以下注释:
传递和处理讯息
经常区分 共享内存并发和消息 传递并发。前者是 通常在本地机器上更有效率 并在“使用”一节中介绍 共享内存并发“稍后 本章。后者扩展到 没有共享的系统 内存,例如,分布式的 系统,也可以用来避免 与...相关的性能问题 共享内存。
我对在没有共享内存的进程之间传递并发的消息感兴趣。 Expert F#和互联网上演示如何使用MailboxProcessor的所有示例都包含此代码的一些变体:
let counter =
MailboxProcessor.Start(fun inbox ->
let rec loop n =
async {
do printfn "n = %d, waiting... " n
let! msg = inbox.Receive()
match msg with
| -1 ->
do printfn "'Til the bitter end..."
return ()
| n -> return! loop(n + msg)
}
loop 0)
counter.Post(20)
counter.Post(50)
counter.Post(-1) // kill mailbox
换句话说,您必须在共享内存中拥有邮箱处理器的句柄,然后才能将邮件发布到其频道。据我所知,这不是Erlang风格的并发,因为你只能在同一个进程中将消息发布到MailboxProcessors(注意:进程,而不是线程)。
一个进程中的一个MailboxProcessor是否可以将邮件发送到另一个MailboxProcessor进程?如果是这样,你能提供样品吗?
答案 0 :(得分:8)
我觉得你对术语感到有些困惑。 Erlang进程不一定直接对应于OS进程。给定的OS进程可以有多个Erlang进程(通常也有),就像你的进程有多个线程一样。如果要在多个OS进程之间进行通信,可能需要查看System.Runtime.Remoting.Channels.Ipc。可以想象,可以围绕这些API创建一个MailboxProcessor风格的包装器。
答案 1 :(得分:8)
MailboxProcessor和AsyncReplyChannel不提供与Erlang中的“pid bang”(Pid!)操作相同的位置透明度。当然,这仅适用于正确配置分布式Erlang节点的情况,即名称,DNS,同步模块,cookie等.OTP中有一些功能可以使管理更容易。当然,如果Erlang进程在同一节点上,它就可以正常工作。但是,分布式Erlang存在一些皱纹。
“网络安全。” 内置的分布式Erlang机制假设网络是安全的。因此,当需要安全性时,采用基于套接字的通信方法和代理Erlang进程。
“网络可靠。” 使分布式Erlang工作的一个原因是它的错误处理理念,即进程不可靠,因此只有通信流程监视器才能实现容错。 OTP编纂模式(即主管)以实现这一理念。 Erlang中的可靠消息传递可以通过Mnesia(一个分布式数据库)实现,就像在RabbitMQ中所做的那样,但是你没有开箱即用。
最后,分布式通信从未如此简单。我们可以在F#中实现AsynchWorker作为我们的代理,并通过AsynchReplyChannel.Send与它进行通信。我们仍然需要考虑分布式计算的谬误。
最后,消息传递样式并发并不意味着进程外通信。它确实意味着没有用锁管理的共享状态,因此是一种更简单,不易出错的并行计算模型。我认为这个Prime Number Sieve是这种并发风格的一个很好的例子。 F#示例不像Squeak或Erlang实现那样美观,因为缺少内置的消息传递语法,但它可以工作。
答案 2 :(得分:1)