terminology.md 6.6 KB
Newer Older
颯沓如流星's avatar
颯沓如流星 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
# 术语及概念
在本章中,我们试图建立一个通用的术语来定义一个坚实的基础,用于交流 Akka 所针对的并发和分布式系统。请注意,对于这其中的许多术语,并没有一个统一的定义。我们试图给出将在 Akka 文档范围内使用的定义。

## 并发 vs. 并行
并发和并行是相关的概念,但有一些小的区别。并发意味着两个或多个任务正在取得进展,即使它们可能不会同时执行。例如,这可以通过时间切片来实现,其中部分任务按顺序执行,并与其他任务的部分混合。另一方面,当执行的任务可以真正同时进行时,就会出现并行。

## 异步 vs. 同步
如果调用者在方法返回值或引发异常之前无法取得进展,则认为方法调用是同步的。另一方面,异步调用允许调用者在有限的步骤之后继续进行,并且可以通过一些附加机制(它可能是已注册的回调、`Future`或消息)来通知方法的完成。

同步 API 可以使用阻塞来实现同步,但这不是必要的。CPU 密集型任务可能会产生类似于阻塞的行为。一般来说,最好使用异步 API,因为它们保证系统能够进行。Actor 本质上是异步的:Actor 可以在消息发送之后进行其他任务,而不必等待实际的传递发生。

## 非阻塞 vs. 阻塞
如果一个线程的延迟可以无限期地延迟其他一些线程,这就是我们讨论的阻塞。一个很好的例子是,一个线程可以使用互斥来独占使用一个资源。如果一个线程无限期地占用资源(例如意外运行无限循环),则等待该资源的其他线程将无法进行。相反,非阻塞意味着没有线程能够无限期地延迟其他线程。

非阻塞操作优先于阻塞操作,因为当系统包含阻塞操作时,系统的总体进度并不能得到很好的保证。

## 死锁  vs. 饥饿 vs. 活锁
当多个 Actor 在等待对方达到某个特定的状态以便能够取得进展时,就会出现死锁(`Deadlock`)。由于没有其他 Actor 达到某种状态(一个`Catch-22`问题),所有受影响的子系统都无法继续运行。死锁与阻塞密切相关,因为 Actor 线程能够无限期地延迟其他线程的进程。

在死锁的情况下,没有 Actor 可以取得进展,相反,当有 Actor 可以取得进展,但可能有一个或多个 Actor 不能取得进展时,就会发生饥饿(`Starvation`)。典型的场景是一个调度算法,它总是选择高优先级的任务而不是低优先级的任务。如果传入的高优先级任务的数量一直足够多,那么低优先级任务将永远不会完成。

活锁(`Livelock`)类似于死锁,因为没有 Actor 取得进展。不同之处在于,Actor 不会被冻结在等待他人进展的状态中,而是不断地改变自己的状态。一个示例场景是,两个 Actor 有两个相同资源可用时。他们每一个都试图获得资源,但他们也会检查对方是否也需要资源。如果资源是由另一个 Actor 请求的,他们会尝试获取该资源的另一个实例。在不幸的情况下,两个 Actor 可能会在两种资源之间“反弹(`bounce`)”,从不获取资源,但总是屈服于另一种资源。

## 竟态条件
当一组事件的顺序的假设可能被外部的非确定性(`non-deterministic`)因素影响时,我们称之为竟态条件(`Race condition`)。当多个线程具有共享可变状态时,常常会出现竟态条件,并且线程在该状态上的操作可能会交错进行,从而导致意外的行为。虽然这是一个常见的情况,但是共享状态不需要有竟态条件。例如,客户机向服务器发送无序数据包(如 UDP 数据报)`P1``P2`。由于数据包可能通过不同的网络路由传输,因此服务器可能先接收到`P2`,然后接收到`P1`。如果消息不包含有关其发送顺序的信息,则服务器无法确定它们是以不同的顺序发送的。根据包(`packets`)的含义,这可能导致竟态条件。

颯沓如流星's avatar
颯沓如流星 已提交
27
- **注释**:Akka 提供的关于在给定的两个 Actor 之间发送的消息的唯一保证是,他们的顺序始终保持不变。详见「[消息传递可靠性](https://codechina.csdn.net/monokai/akka-guide/blob/master/articles/general-concepts/message-delivery-reliability.md)」。
颯沓如流星's avatar
颯沓如流星 已提交
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

## 非阻塞保证(进度条件)
如前几节所讨论的,阻塞是不可取的,原因有几个,包括死锁的危险和系统中吞吐量的降低。在下面的章节中,我们将讨论具有不同强度的各种非阻塞特性。

### 等待自由
如果保证每个调用都以有限的步骤完成,则方法是无等待的,即等待自由(`wait-freedom`)。如果一个方法是有界“无等待”的,那么步骤的数量有一个有限的上限。

根据这个定义,无等待方法永远不会被阻塞,因此不会发生死锁。此外,由于每个 Actor 都可以在有限的步骤之后(调用完成时)继续进行,因此无等待方法没有饥饿。

### 锁自由
锁自由(`lock-freedom`)比等待自由更弱。在无锁调用的情况下,某些方法以有限的步数完成可能导致无限的等待。这个定义意味着没有死锁的调用是不可能的。另一方面,某些调用以有限的步骤完成的保证不足以保证所有调用最终都完成。换句话说,锁自由不足以保证不发生饥饿。

### 障碍自由
障碍自由(`obstruction-freedom`)是本文讨论的最薄弱的非阻塞保证。如果一个方法在某个时间点之后独立执行(其他线程不执行任何步骤,例如:挂起),则该方法称为无障碍的,它以有限的步骤完成。所有锁自由对象都是无障碍的,但相反的情况通常是不正确的。

乐观并发控制(OCC)方法通常是无障碍的。OCC 方法是,每个 Actor 都试图在共享对象上执行其操作,但如果 Actor 检测到来自其他对象的冲突,则会回滚修改,并根据某些计划重试。如果有一个时间点,其中一个 Actor 是唯一的尝试者,那么操作将成功。

## 推荐文献
- The Art of Multiprocessor Programming, M. Herlihy and N Shavit, 2008. ISBN 978-0123705914
- Java Concurrency in Practice, B. Goetz, T. Peierls, J. Bloch, J. Bowbeer, D. Holmes and D. Lea, 2006. ISBN 978-0321349606

----------

**英文原文链接**[Terminology, Concepts](https://doc.akka.io/docs/akka/current/general/terminology.html).

----------
颯沓如流星's avatar
颯沓如流星 已提交
54
———— ☆☆☆ —— [返回 -> Akka 中文指南 <- 目录](https://codechina.csdn.net/monokai/akka-guide/blob/master/README.md) —— ☆☆☆ ————