为什么演员收到的消息是无序的?

时间:2011-04-22 03:26:43

标签: scala concurrency actor

我一直在研究actor模型(特别是Scala中的实现),但我无法理解为什么要求消息没有按特定顺序到达。

似乎至少有一些优雅的,基于actor的并发问题解决方案,只有消息按顺序到达时才会起作用(例如,生产者 - 消费者变体,延迟数据库写入,并发安全缓存)。

那么为什么演员的消息没有按顺序到达?是允许有效实现还是防止在订购消息时出现某种死锁?

4 个答案:

答案 0 :(得分:12)

我的印象是,如果两个线程向一个演员a发送一条消息,则没有特别保证演员首先接收到哪一个。但是,如果您的代码看起来像

a ! "one"
a ! "two"

然后a将始终在"one"之前获得"two"(尽管谁知道其他线程之间可能还有其他内容)。

因此,我不认为消息根本没有特定的顺序。来自一个线程内的多条消息(根据我从代码或经验中可以看出)将按顺序到达。

答案 1 :(得分:9)

我不知道为什么Scala的Actors(标准库中的那些,无论如何 - 还有Aka的Akka,Lift和Scalaz实现)选择了这个特定的实现。可能是Erlang自身限制的副本 - 但没有两个单线程之间通信的保证。或许也有这种保证 - 我希望Phillip Haller在这里发表评论。

但我确实质疑你关于并发问题的陈述。在研究异步分布式算法时,一个基本原则是您不能保证任何订单的消息接收。

引用Distributed Computing: Fundamentals, Simulation and Advanced Topics,Hagit Attiya和Jennifer Welch,

  

如果系统没有固定的上限,系统被称为异步   需要传递消息或连续之间经过多长时间   处理器的步骤。

actor模型是异步模型。这使它能够在分布式硬件上工作 - 无论是通过网络进行通信的不同计算机,还是不提供同步保证的系统上的不同处理器。

此外,即使是多核处理器上的多线程模型也大多是异步的,同步的原语非常昂贵。

所以问题的简单答案可能是:

不保证消息按顺序到达,因为这是异步系统的潜在限制,这是演员使用的基本计算模型。

这个模型是我们在任何通过TCP / IP分布的系统上实际存在的模型,也是i386 / x64多核/多处理器硬件上最有效的模型。

答案 2 :(得分:3)

以下简单示例显示了按顺序到达非常简单的actor的消息:

import scala.actors._
import scala.actors.Actor._
import scala.collection.mutable._

val adder = actor {
  loop {
    react {
      case x: Int => println(" Computing " + x); reply(x+2)
      case Exit => println("Exiting"); exit
    }
  }
}

actor {
  for (i <- 1 to 5) {
    println("Sending " + i)
    adder !! (i, { case answer => println("Computed " + i + " -> " + answer) })
  }

  println("Sending Exit")
  adder !! Exit
}

以下是使用Sun JDK 1.6.0u25在Windows 64位上使用Scala 2.9.0 final执行上述代码的一次输出:

Sending 1
Sending 2
Sending 3
Sending 4
Sending 5
Sending Exit
 Computing 1
Computed 1 -> 3
 Computing 4
Computed 4 -> 6
 Computing 3
Computed 3 -> 5
Exiting

答案 3 :(得分:2)

你会选择什么样的顺序?应该是在他们被送去还是收到他们的时候?在我们对邮件进行排序时,我们应该冻结整个邮箱吗?想象一下,对一个大而近乎完整的邮箱进行排序,是否会对队列进行任意锁定?我认为消息没有按顺序到达,因为没有保证执行此类订单的方法。我们在网络和处理器之间存在延迟。

我们不知道消息来自哪里,只知道它们已经到达。那么这个怎么样,我们保证我们没有订购,甚至没有考虑订购。而不是必须提出一些令人印象深刻的逻辑来保持组织有序,同时尽可能保持无争用,我们可以专注于尽可能保持争用。

其他人可能比我对此有更好的答案。

修改

现在我已经有时间睡觉了,我认为这是一个规定,可以创建一个更有活力的Actor生态系统。因此,为什么要从线程池中限制一个Actor或一个线程或线程的部分所有权?如果有人希望拥有一个可以尽可能多地获取线程的Actor来尽可能多地处理其邮箱中的消息呢?

如果您事先做出规定,必须按照他们继续进行的顺序完成消息,那么您永远无法允许这样做。可以由Actor分配多个线程来处理邮箱中的邮件,这样您就无法控制首先处理的邮件。

Phew,你的梦想在你睡觉时对你的思想所说的。