Erlang进程以什么顺序使用消息?

时间:2011-07-28 09:34:02

标签: erlang

邮件是以先到先得的方式处理还是按时间戳或类似的方式排序?

3 个答案:

答案 0 :(得分:12)

在进程和另一个进程之间保留消息顺序。阅读FAQ

  

10.9是否保证了信息接收的顺序?

     

是的,但只在一个过程中。

     

如果有实时进程,则发送消息A然后发送消息   B,保证如果消息B到达,则消息A到达之前   它

     

另一方面,假设进程P,Q和R.P发送消息A.   Q,然后消息B到R.不能保证A到达   在B之前。(如果这样,分布式Erlang将会非常艰难   是必需的!)

@knutin关于如何在流程中使用消息是正确的。另外,请注意您可以使用两个后续接收语句来确保在之后消耗某个消息:

receive
  first ->
    do_first()
end,
receive
  second ->
    do_second()
end

接收声明正在阻止。这样可以确保您do_second()之前永远不会do_first()。与@kututin的第二个解决方案的不同之处在于,在这种情况下,如果某个重要的东西在重要之前到达,则将重要位置排队。

答案 1 :(得分:4)

邮箱始终按邮件到达的顺序保存。

但是,消息的消费顺序取决于您的代码。

如果您的普通receive子句有一个接收任何内容的普通进程,则获取消息的顺序与它们到达的顺序相同。

loop() ->
   receive
        Any ->
            do_something(Any),
            loop()
   end.

但是,如果您有一个带有匹配子句的选择性receive,它将在邮箱中搜索此特定类型的邮件并使用第一个匹配的邮件,从而有效地跳过不匹配的邮件。在以下示例中,如果队列中标记为重要的消息,则将在任何其他消息之前处理它们。注意:这样的匹配将搜索队列中的所有消息,这对许多消息都是一个问题。这个领域有一些发展,但我没有达到速度。

loop() ->
    receive
        {important, Stuff} ->
            do_something_important(Stuff),
            loop();
        Any ->
            do_something(Any)
            loop()
     end.

答案 2 :(得分:1)

为了进一步定义答案,我想指出这样一个事实:如上所述,没有模式匹配的消息被跳过,但实际上它们被简单地放在一边然后按顺序重新引入(所以首先是用于下一次接收模式匹配的其他消息(在不匹配的消息之后到达)。

当你有一个gen_server行为模块时,这个问题确实表现得最糟糕,因为在这种情况下,总是有相同的模式匹配调用方案,不在范围内的消息将泛滥消息队列,除非你定义一个(丑陋的)并且容易出错,恕我直言)匹配所有模式如:

receive
    ... -> ...;
    ... -> ...;
    MatchAllPatterns -> ok.
end