并发vs并行
异步vs同步
非阻塞vs阻塞
当我们谈到阻塞时,一般是指一个线程的延迟能会导致其它一些线程无限期的延迟。这里有一个例子,有一个资源只能被一个线程使用互斥手段独占使用。如果一个线程永远不释放资源(比如意外地进入了某个无限循环),其它等待的线程将不能进行工作。相对的,非阻塞就是指一个线程不会无限期的延迟其它线程。 一般认为非阻塞操作比阻塞操作要好,但随着系统的整体发展,并不能保证不包含阻塞操作。
死锁vs饥饿vs活锁
当一些参与者都在等待对方到达某个特定状态时才能进行下一步工作,此时就会发生死锁。在其它参与者没能到达某个状态的情况下(Catch-22问题),所有参与者都无法进行工作,此时整个系统停止运转。死锁与阻塞密切相关,这是因为一个线程有能力阻塞其它线程的运行是必要的条件。 在死锁的情况里没有参与者可以运行,而当饥饿发生时有一些参与者可以运行,但有一个或更多的参与者无法运行。一个典型的场景是一种简单的调度算法,它每次都选择高优先级的任务。如果高优先级的任务不断的到来,所有的低优先级任务将永远无法完成。 活锁与死锁类似,也是没有参与者可以进行工作。不同之处在于不再是一直等待其它参与者的处理状态,而是不断的改变自己的状态。举个例子,如果两个参与者拥有两个相同的可用的资源,它们都尝试获取这个资源,但它们也去检查对方是否需要这个资源。如果某个资源被另一个参与者请求了,它们就尝试获取另一个资源。在运气不好的情况下两个参与者会在两个资源之间跳跃,永远无法获取它们,永远再给对方让步。
竞争条件
当预先设想的一系列事件的顺序会被外部非确定因素违反时就称之为竞争条件。当多个线程拥有一个共享的状态时竞争条件经常会发生,线程对这个状态的操作也许会交错执行,而产生了意想不到的行为。对于竞争条件来说共享状态并不是必须的。举个例子,一个客户端给服务器发送无序的包P1,P2(比如UDP数据报)。这些包也许会经过不同的网络传输而来,服务器可能先收到P2然后才收到P1.如果消息没有包含发送顺序的信息,那么服务器是无法确定它们的顺序。根据这些包的含义,这就会产生竞争条件。
非阻塞保证()
之前几节的讨论可以看到由于一些原因阻塞是不可取的,它会导致系统产生死锁和吞吐量减少的危险。接下来我们讨论不同的非阻塞特性以及各自的优势。
无等待
对一个方法而言,如果对它的每次调用都可以保证在有限步骤内完成,就称它为无等待的。如果一个方法是无等待的,则它的步骤拥有一个有限的上界。 无等待的方法是不会阻塞的,因此死锁也不会发生。 此外,由于每个参与者都可以在有限步(调用完成)后继续工作,无等待方法也不会发饥饿
无锁
无锁是比无等待要弱的特性。在无锁情况下,大多数方法都会在经过有限步后完成。这个定义表明对于无锁调用是不会发生死锁的。另一方面,一些调用在有限步后完成并不足以保证所有的调用最终都会完成。换句话说,无锁不能保证饥饿不会发生。
无阻碍
无阻碍是这里介绍的最弱的非阻塞保证。如果一个方法执行在隔离环境中(其它线程被挂起),它在有限的步骤内执行完毕,就称它为无阻碍的。所有的无锁对象都是无阻碍的,反之不成立。
乐观并发控制(OCC)方法通常是无阻碍的。OCC方法是指每个参与者都尝试在共享对象是执行自己的操作,但当一个参与者探测到来自其它参与者的冲突时,就将所做的修改进行回滚,然后根据调度策略再去尝试。如果有在某个时间,只有一个参与者在尝试,这个操作就会成功。