为了定义一个无歧义的称之为'Akka'的并发、分布式通迅系统,在这一章里我们打算约定一些标准的术语。然而,需要注意这些术语的定义仅用于此文,它们在别的文献可能有其它含义。因此这些术语适用范围约束仅在'Akka'的文档内。
并发与并行
并发和并行是相关的概念,但有小的差异。并发意味两个或更多作业将要处理,并不表示它们会同时执行。就比如说我们将所有作业的可分为多个时间切片段,即可以按时间顺序执行下去,也可以在一定情况下跳跃到其它作业上混合执行。并行则强调了作业执行的同时性。
异步与同步
我们所熟知的同步方法是指方法调用后会出现返回值或抛出异常否则无法继续执行的方法调用。另一方面,异步方法是指允许调用者处理其它有限的步骤,并可能通过其它机制发送相关信号完成方法 。(它可能是某种注册的回调,预期或一个消息)
打算同步的API并没有必要通过阻塞实现同步。具有集中任务的特定CPU可以用同样的行为做为阻塞。一般来说为使系统可以持继运行,首选采用异步API。Actor是天生异步的。每个actor在发送消息后并不需要等待被交付后再处理。
非阻塞和阻塞
我们指的阻塞是指能引起其它线程无限延迟的一个延迟的线程。典型的例子是只使用一个线程的互诉操作。如果线程独占资源(比如意外执行无限循环)其它线程装只能等待而不能处理。相对而言,非阻塞是指没有线程能无限延迟其它线程。
由于对整个系统而言,包含阻塞是非常不确定的因些非阻塞操作优于阻塞。
死锁、互拆等待和活锁
死锁出现在几个参与者相互等待达到一个特定的状态才能继续处理。由于没有参与者能其他参与考达到特定状态时继续处理,所有的子系统都将停滞。(如同Catch-22问题)死锁阻塞密切相关,参与者的线程能够推迟其他线程的处理是非常必要的功能。
在死锁时其实是互拆等待状态,参与者无法继续处理,他们中能继续处理而实际没有实际处理。典型场景是调度算法单纯的总是在低优先级的任务中选择高优先级任务。如果传入的高优先级任务的数量足够高,那么低优先级的任务将完成。
与死锁类似的是,活锁也没有参与者执行处理。而与死锁不同的是参与者不变改变自已的状态,而不是等待别人改变状态。比如有两个参与者和及两个相同的资源。它们都试图得到资源,同时也检查对方也需要资源。如果另一个参与者已请求资源,它们则试图得到另一个资源的实例。而也有不幸的情况,两个参与者在两个资源间互相“弹”开,屈从于对方而从不获得资源。
竞态选择
我们把一组假定有顺序的事件受外部不确定事件影响而紊乱的情况称为竞态选择。竞态选择时常常出现在多个线程共享可变状态,是操作的线程状态可能是交叉造成意想不到的行为。虽然常见的情况下共享状态没有必要成为竞态选择。举个例子一个客户端发送无序数据包(例如UDP数据包)P1,P2到服务器。数据包在传输时可能经过不同路由的网络线路,服务器可能首先收到P2,再收到P1 。如果消息中不含发送时的顺序信息,那么服务器将无法确定发送的顺序。依据数据包就引起了竞态选择。
注意
Akka提供的actor传递消息的机制保证的顺序是不变的。参见消息传递的可靠性。
非阻塞类别(处理的策略)
前面几节中谈到引起系统中死锁和吞吐量降低的危险是阻塞不受欢迎的几个原因。下文我们将讨论各种非阻塞特点。
无等待
无等待方面是指每个调用确保用有限的步骤完成。只要方法是有限的无等待那么完成步骤的数量是必有上限。
从这个定义看无等待方法从未被阻塞,因此不会发生死锁。此外,每个参与者可以有限的步骤之后(当调用完成)执行,无等待没有竞态选择。
无锁定
无锁定的性能弱于无等待。在无锁定的情况下,绝大多数情况是部分方法在有限的步骤内完成。这个定义意味着非死锁可能被无锁定调用。另一方面,一些有限步骤调用完成前无法保证它们最终完成。换句话说,无锁定并无法保证没有竞态选择。
无阻碍
无阻碍这里讨论的最弱的非阻塞保证。无阻碍是指在它有限的步骤中开始执行后一个时间点进行隔离(其它线程没有步骤,好比是挂起)。所有的无锁定对象是无阻碍的,这是一个充分条件。
乐观并发控制(OCC)方法通常属于无阻碍。OCC方法是指每个参与者试图共享对象上执行的操作,但如果某一个参与者发现和别人冲突则回滚的修改,根据调度再次尝试。如果在一个时间点上参与者是唯一一个则操作成功。