我在第379页的Expert 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进程?如果是这样,你能提供样品吗?
我觉得你对术语有点困惑.Erlang进程不一定直接对应于OS进程.给定的OS进程可以有多个Erlang进程(通常也有),就像你的进程有多个线程一样.如果要在多个OS进程之间进行通信,可能需要查看System.Runtime.Remoting.Channels.Ipc.可以想象,可以围绕这些API创建MailboxProcessor样式的包装器.
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#的例子并不像佳乐或一个Erlang实现作为美观的,因为缺乏内置的语法消息传递,但它的作品.