7

Priority receive in Erlang can easily be implemented as follows:

prio() -> 
  receive 
    {priority, X} -> X 
  after 0 -> 
    receive 
      X -> X 
    end 
  end.

I am reading a paper called Priority Messaging made Easy, by Nyström, in which they describe the following problem:

The main problem with the [code] example [above], is that we do not take into consideration that when evaluation is resumed from the inner blocking receive we may have more than one message in the mailbox. In a worst case scenario, all but the first, of potentially a huge number, of elements could be priority messages. In this scenario we would actually have accomplished the very opposite of what we intended to do.

I don't completely get this.

Question (1): I assume that the inner blocking receive will be 'called' (i.e. resumed) as soon as one message has arrived in the message queue, right? Is it realistic to assume that in the short time it takes to resume from the inner blocking receive, there would already be a whole bunch of messages waiting in the queue?

Question (2): Also, the worst case scenario is described as a queue with one normal message and a lot of priority messages. Since all the receive clauses are first checked against the first message in the queue, and then against the second message in the queue, ...(source: this book, page 69-70) shouldn't this be: a lot of normal messages with at the end of the queue a priority message?

4

4 回答 4

6

Erlang 是一种完全并发的语言,没有理由不能同时发送多条消息。沿着“哦,这很快——其他线程不太可能在那么短的时间内做一些冲突的事情”这样的假设,本质上与闭上眼睛说“没有竞争条件这样的事情,有没有比赛条件之类的东西……”

于 2009-06-06T16:37:10.707 回答
5

关于(1):是否可以做出这种假设取决于您的具体情况。例如,所有其他进程在向您发送消息之前可能一直在等待某些事情发生。

关于(2):事实上,在我看来,最坏的情况是没有优先消息,因为每次都必须遍历邮箱:“有优先消息进来了吗?”

于 2009-06-07T04:36:31.973 回答
2

您强调的声明只是说,如果您处于阻塞内部接收块中,您可以在高优先级消息之前处理低优先级消息(因为您正在匹配所有内容),这不一定是意图。

这有点极端——我发现当你想要某种类型的过滤时,高效地处理消息很重要。在其他情况下,我还监控了进程队列深度并相应地改变了我的策略。作为后者的一个示例,一个简单的日志记录 gen_server 类型进程(用于发送日志消息)可能会得到相当备份,因为将日志消息写入磁盘可能比将消息推送到进程慢很多。如果队列深度太大,我会丢弃我通常记录的信息/垃圾邮件类型的消息,只处理(写入磁盘)关键消息。

于 2009-06-08T20:05:32.510 回答
2

根据erlang参考手册receive按时间顺序遍历邮箱。并阻塞,直到消息与其中一个子句匹配。

鉴于听起来内部接收将阻塞,直到它收到匹配的消息。因此,您实际上可能会在等待与您想要的相反的非优先级消息时堆叠优先级消息。

摆脱这种困境的方法是在内部接收上抛出一个新的 after 子句。或者总是在内部接收中匹配。

尽管查看它们的功能,内部子句应该始终匹配,但我猜这就是他们所说的。

于 2009-06-07T21:52:07.333 回答