6.7.2 通信死锁

到目前为止,我们所有的工作都着眼于资源死锁。一个进程需要使用另外一个进程拥有的资源,因此必须等待直至该进程停止使用这些资源。有时资源是硬件或者软件,比如说CD-ROM驱动器或者数据库记录,但是有时它们更加抽象。在图6-2中,可以看到当资源互斥时发生的资源死锁。这比CD-ROM驱动器更抽象一点,但是在这个例子中,每个进程都成功调用一个资源(互斥锁之一)而且死锁的进程尝试去调用另外的资源(另一个互斥锁)。这种情况是典型的资源死锁。

然而,正如我们在本章开始提到的,资源死锁是最普遍的一种类型,但不是惟一的一种。另一种死锁发生在通信系统中(比如说网络),即两个或两个以上进程利用发送信息来通信时。一种普遍的情形是进程A向进程B发送请求信息,然后阻塞直至B回复。假设请求信息丢失,A将阻塞以等待回复,而B会阻塞等待一个向其发送命令的请求,因此发生死锁。

仅仅如此并非经典的资源死锁。A没有占有B所需的资源,反之亦然。事实上,并没有完全可见的资源。但是,根据标准的定义,在一系列进程中,每个进程因为等待另外一个进程引发的事件而产生阻塞,这就是一种死锁。相比于更加常见的资源死锁,我们把上面这种情况叫做通信死锁(communication deadlock)。

广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元

通信死锁不能通过对资源排序(因为没有)或者通过仔细地安排调度来避免(因为任何时刻的请求都是不被允许延迟的)。幸运的是,另外一种技术通常可以用来中断通信死锁:超时。在大多数网络通信系统中,只要一个信息被发送至一个特定的地方,并等待其返回一个预期的回复,发送者就同时启动计时器。若计时器在回复到达前计时就停止了,则信息的发送者可以认定信息已经丢失,并重新发送(如果需要,则一直重复)。通过这种方式,可以避免死锁。

当然,如果原始信息没有丢失,而仅仅是回复延时,接收者可能收到两次或者更多次信息,甚至导致意想不到的结果。想象电子银行系统中包含付款说明的信息。很明显,不应该仅仅因为网速缓慢或者超时设定太短,就重复(并执行)多次。应该将通信规则——通常称为协议(protocol)——设计为让所有事情都正确,这是一个复杂的课题,超出了本书的范围。对网络协议感兴趣的读者可以参考作者的另外一本书——《Computer Networks》(Tanenbaum,2003)。

并非所有在通信系统或者网络发生的死锁都是通信死锁。资源死锁也会发生,如图6-15中的网络。这张图是因特网的简化图(极其简化)。因特网由两类计算机组成:主机和路由器。主机(host)是一台用户计算机,可以是某人家里的PC机、公司的个人计算机,也可能是一个共享服务器。主机由人来操作。路由器(router)是专用的通信计算机,将数据包从源发送至目的地。每台主机都连接一个或更多的路由器,可以用一条DSL线、有线电视连接、局域网、拨号线路、无线网络、光纤等来连接。

阅读 ‧ 电子书库
图 6-15 一个网络中的资源死锁

当一个数据包从一个主机进入路由器时,它被放入一个缓冲器中,然后传输到另外一个路由器,再到另一个,直至目的地。这些缓冲器都是资源并且数目有限。在图6-15中,每个路由器都有8个缓冲器(实际应用中有数以百万计,但是并不能改变潜在死锁的本质,只是改变了它的频率)。假设路由器A的所有数据包需要发送到B,B的所有数据包需要发送到C,C的所有数据包需要发送到D,然后D的所有数据包需要发送到A。那么没有数据包可以移动,因为在另一端没有缓冲器。这就是一个典型的资源死锁,尽管它发生在通信系统中。