几个基本概念

并发vs.并行

并发和并行是互相相关的概念,但是还是有一些细微的区别。并发是两个或者多个任务在进行中,虽然他们不是真的在同时进行。举例的话,这个可以通过时间切片的方法实现,即把任务切割成多个部分,并混合在一起序列化运行。相反,并行就是真的能同时运行。

异步vs.同步

如果一个方法不返回值或者抛出异常,这个方法的调用点就不能往下运行,那这个调用这个方法就是同步的。相反,一个异步调用允许调用者在执行有限的步骤后继续执行,并且方法的结束是信号化的,这种信号化通过一些附加机制实现(这些机制可能是一个注册的回调函数,一个Future,一个消息等)。

一个同步API可能使用阻塞来实现同步,但这不是必要的。一个密集CPU任务可能也会引起类似的阻塞行为。一般而言,由于异步API保证系统可以继续执行,所以其更受偏好。Actor天然就是异步的:一个Actor可以在发出一条消息后,不许要等待消息真地发出去即可继续执行后续工作。

非阻塞vs.阻塞

如果某个线程的延迟可以无限期地延迟其他其他线程,我们就说这是阻塞。一个直观的例子是,一个资源可以一直被一个线程排他地占用。如果一个线程无限期地占有某个资源(例如意外运行了一个死循环)而其他线程一直等着资源而不能往下执行。与之相对,非阻塞就是没有线程能无限期地延迟其他线程。

由于当系统包含阻塞操作时,并不能在细节上保证系统的整体动作可继续执行,所以相比阻塞操作,一般都选择非阻塞操作。

死锁vs.饥饿vs.活锁

当各个参与者都在等待其他参与者达到一个能让自己继续执行的特定状态时,死锁就会发生。因为他们之中任何一个参与者在其他参与者没有达到一个特定状态之前都不能继续执行,这时所有相关的子系统都会抛锚。死锁与阻塞关系很近,因为在死锁中,一个参与者线程也能无限期延迟其他线程。

在死锁的情况中,没有一个参与者能继续往下执行,在与之相对地就有饥饿,当饥饿发生时有参与者可以继续执行,但是可能会有一个或者多个参与者不能执行。一种典型的情况是相比优先级更低的任务一直选择高优先级的任务朴素的调度算法。如果输入的高优先级任务的数量一直很高,则优先级较低的任务永远不会被完成。

活锁和死锁有些类似,也是没有一个参与者可以继续执行。不同的地方在于死锁是各个参与者处于一个一直在等待其他参与者的冻结状态中,活锁是参与者在持续地改变他们的状态。一个示例情况是,当两个参与者有两个一样的可用资源。他们各自都尝试获取资源,但是他们同时也检查是否有别人需要这个资源。如果资源被其他参与者请求了,他们就尝试获取另一个实例或资源。不走运的情况下,可能会发生两个参与者在两个资源间『反弹』,永远在获得它,但永远屈服于另一个参与者。

竞争条件

一个事件集的假定序列可能被外在非决定性结果侵犯,我们称这种情况为竞争条件。竞争条件经常发生在多线程有一个共有的状态,且线程对状态的操作可能会被干扰,从而引发意料之外的行为。这是一个一般的情况,竞争条件并不一定要一个共享的状态。例如客户端发送无序的包(如UDP报文)P1,P2到服务器。由于包可能走不同的路由,服务器可能先收到P2再收到P1。若果消息没有包含他们的发送顺序的信息,服务器决定的包的顺序就可能是一个不同的顺序。根据包的含义,这也可能的引发竞争条件。

非阻塞保证(进行条件)

之前小节中说了,由于如死锁的危险,减少吞吐量之类的原因,阻塞是不受欢迎的。在接下来的章节中我们讨论几种不同能力非阻塞的特性。

等待自由

如果方法每次调用都保证能在有限步骤内完成的话,这种方法就称为等待自由方法。如果一个方法界定为等待自由,那该方法能在有限步骤内完成。

这个定义表明了等待自由方法永远非阻塞,因此死锁不可能发生。此外,由于每个参与者都可以在有限步骤的调用后(当调用结束)继续运行,自由等待方法也不会发生饥饿。

锁自由

锁自由是一种比等待自由弱一点的特性。在锁自由调用中,部分方法在有限步骤内完成是极其经常的。这个定义表明死锁在锁自由中是不可能的。另一方面,保证部分调用在有限步骤内结束并不保证所有调用最终都能结束。也就是说,锁自由不足以保证不发生饥饿。

堵塞自由

堵塞自由是这里讨论的最弱的非阻塞保证。如果一个方法有一个时间点是在隔离中执行(其他线程没有步骤,例如被挂起),则其被称为堵塞自由方法,它能在有限步骤内执行完成。所有的锁自由对象都是堵塞自由,但反过来则未必。

乐观并发控制(OCC)方法一般都是堵塞自由。OCC是所有的参与者都尝试在一个共享对象上执行自己的操作,但如果一个参与者发现和其他参与者有冲突,它就会回滚修改,然后根据一些日程规划再一次尝试。如果在某个时间点某个参与者是唯一一个在尝试的,该操作就会成功。

###文献推荐

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

参考

  1. Terminology, Concepts - Akka

[2]: