(1)进程终止后,是否可能将pid
重新分配给spawn()
创建的其他进程?
(2)如果是这样,通讯安全如何?例如,向邮件发件人的Pid
发送回复。如果发件人已崩溃,我们怎么知道此Pid
现在不属于另一个进程?
(3) pid重用有什么保证?例如,在重用pid之前是否有最小间隔?
(4)通常采取哪些措施来防止因重复使用pid而导致的错误?它被简单地忽略了吗?
答案 0 :(得分:5)
很多问题......
一方面没有详尽无遗,而另一方面又过于迂回,请考虑一个实际的例子:OTP函数Erlang reference。
当您使用gen_server:call/2,3
时,gen_server模块除了监视正在发送消息的进程外,还会生成一个看起来像{self(), make_ref()}
的组合消息标记。发送过程保证至少如果它正在调用的进程在发送回复之前死亡,将接收监视器退出消息而不是响应,并且死亡进程的PID将与它刚刚调用的PID匹配。接收消息的接收进程将同时接收发送方的PID和一个保证在本地唯一的Erlang引用(至少在相当长的时间内 - 我相信独特性在数十亿美元的某处。当它发送响应时,接收进程也必须知道此引用,并且由最初用于发送的PID进行寻址。
有可能(虽然极不太可能)发送进程可能已经死亡,并且可以使用相同的PID重新生成新进程,但是其他进程几乎不可能使用相同的PID 生成并在gen_server:call/2,3
消息上阻塞,该消息碰巧具有与旧的死时调用相同的内部运行时引用。
除了这种近乎不可能性之外,让我们考虑一个世界,这个世界真的发生了这个奇怪的事情并且所有保护措施都失败了......
(大约2^64 * 2^64 * chance_of_failure_on_this_tiny_scale()
)
发送过程会得到一个奇怪的响应消息,几乎肯定会失败一个断言匹配并在下一行死掉,并在已知状态下重启。同样问题发生两次的可能性可能低于接下来几分钟内质子衰减的可能性。
这是"正确性"?不。在大规模并发系统中,没有可证明的正确性。这就像试图"证明"代表全人类的单一方程式。大多数Erlang系统本质上都是混乱的,因此通常无法证明系统。您可以证明的是单个纯函数是正确的,并且副作用进程在其生命周期中可能调用的所有函数都有明确的终止条件包括崩溃在不稳定的数据上。最后一部分是Erlang如何实现如系统的强大稳健性(良好的编码实践,遵守功能原则以及使用Dialyzer的强大文化也有很大帮助)。
所以..."正确性" ...尽可能多地证明功能。这是一件好事,为什么我们有像PropER和QuickCheck这样的工具。作为一套通用指南,请尽量写下:
=
。这就是为什么Erlang的=
是一致的分配,断言和统一。除非你在学术界(这个功能可能会把一个巨大的世界称为下面的东西,所以这不是一个非常大的限制),以比功能更大的比例进行校对是一个愚蠢的错误。 。不可能或锁定条件的校对协议也是可能的,如果你有时间,那就去吧(否则做我们其他人做的事情,坚持超时和返工过去实际上超时的代码) - 这不应该是经常发生的事。)
所有这一切...... Steve-O几乎肯定会在数据中心的数据线上绊倒,并且在接下来的两年内将群集拆分的次数比任何人都可能看到PID环绕导致实际的更多次未来十年的冲突。