erlang可以重用进程ID吗?如果是这样,如何确定正确性?

时间:2017-09-10 06:57:12

标签: erlang

(1)进程终止后,是否可能将pid重新分配给spawn()创建的其他进程?

(2)如果是这样,通讯安全如何?例如,向邮件发件人的Pid发送回复。如果发件人已崩溃,我们怎么知道此Pid现在不属于另一个进程?

(3) pid重用有什么保证?例如,在重用pid之前是否有最小间隔?

(4)通常采取哪些措施来防止因重复使用pid而导致的错误?它被简单地忽略了吗?

1 个答案:

答案 0 :(得分:5)

很多问题......

  1. 是。 PID可以重复使用。
  2. 沟通是安全的(ish)"因为以任何一致性命中重复使用的PID的可能性极小。点击网络和硬件错误非常比这更可能。 我们设计了面向的健壮性程序,其中包括可以接受错误消息和/或过程自发死亡的方式编程(这种死亡的成本构建在重启周期中)。
  3. 对它的保证至少基于我对主要EVM实现(例如HiPE不确定)的经验,因为整数赋值空间非常大在大多数情况下,发送消息比整数环绕要快得多。
  4. 基于PID重用避免怪异的关键是将其与其他 在典型使用范围内的唯一值相结合 - 并且通常采用{{{ 3}}。
  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的=是一致的分配,断言和统一。
    • 具有可证明状态的协议。例如,您无法以阻塞的方式使两个相同的进程相互调用,而不会出现死锁的风险。这是并发系统的基本限制。 CAP定理是另一个定理。根据这些约束设计您的系统(这是奇怪的解放)并且有意识地选择您的权衡

    除非你在学术界(这个功能可能会把一个巨大的世界称为下面的东西,所以这不是一个非常大的限制),以比功能更大的比例进行校对是一个愚蠢的错误。 。不可能或锁定条件的校对协议也是可能的,如果你有时间,那就去吧(否则做我们其他人做的事情,坚持超时和返工过去实际上超时的代码) - 这不应该是经常发生的事。)

    所有这一切...... Steve-O几乎肯定会在数据中心的数据线上绊倒,并且在接下来的两年内将群集拆分的次数比任何人都可能看到PID环绕导致实际的更多次未来十年的冲突。