繁体   English   中英

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

[英]Why are messages received by an actor unordered?

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

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

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

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

a ! "one"
a ! "two"

那么a总是会在"two" "one"之前得到"one" (虽然谁知道其他线程之间可能还有什么)。

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

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

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

引用Hagit Attiya和Jennifer Welch的分布式计算:基础,模拟和高级主题

如果对于消息传递所花费的时间或处理器的连续步骤之间经过了多长时间没有固定的上限,则称系统是异步的。

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

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

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

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

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

以下简单示例显示了按顺序到达非常简单的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

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

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

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

编辑:

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM