6.1 死锁的引入
在之前我们或多或少都涉及到了死锁,最直接的例子就是哲学家就餐筷子,如果每一个哲学家都拿起了他的右手的筷子,现在都在等左边的筷子。这样一直绕下去,从而产生了死锁。
6.1.1 资源问题
在系统中存在着很多不同类型的资源,其中可以引起的死锁的主要是需要采用互斥访问方法的、不可以被抢占的资源、
6.1.1.1 可重用性资源和消耗性资源
可重用性资源
可重用性资源是一种可供用户重复使用多次的资源,它具有以下性质:
- 每一个可重用性资源中的单位只能分配给一个进程使用,不允许多个进程共享
- 进程在使用可重用性资源时,须按照这样的顺序:请求资源 -> 使用资源 -> 释放资源
- 系统中每一类可重用性资源中的单元数目是相对固定的,进程在运行期间既不能创建也不能删除它
可消耗性资源
可消耗性资源又称为临时性资源,它是在进程运行期间,由进程动态的创建和消耗的,它具有以下性质:
- 每一类可消耗性资源的单元数目在进程运行期间是可以不断变化的,有时它可以有很多,有时可能为0
- 进程在运行过程中,可以不断地创造可消耗性资源的单元,将它们放入该资源类的缓冲区中,以增加该资源类的单元数目
- 进程在运行过程中,可以请求若干个可消耗性资源单元,用于进程自己的消耗,不再将它们返回给该资源类中
6.1.1.2 可抢占性资源和不可抢占性资源
可抢占性资源
可把系统中的资源分为两类,一类是可抢占性资源,是指某进程在获得这类资源后,该资源可以再被其它进程或系统抢占
不可抢占性资源
另一类资源是不可抢占资源,一旦系统把某资源分配给该进程之后,就不能将它强行回收,只能在进程用完后自行释放
6.1.2 死锁的起因
6.1.2.1 竞争不可抢占性资源引起的死锁
通常系统中所拥有的不可抢占性资源其数量不足以满足多个进程运行的需要,使得进程在运行过程中,会因争夺资源而陷入僵局。
一个很简单的例子,进程 P 1 P_1 P1和 P 2 P_2 P2在并发执行,他们都要写两个文件 F 1 F_1 F1和 F 2 F_2 F2。其中 P 1 P_1 P1和 P 2 P_2 P2的代码分别为:
P1
....
Open(f1, w);
Open(f2, w);
P2
....
Open(f2, w);
Open(f1, w);
如果这两个进程在并发执行的时候,如果 P 1 P_1 P1先打开 F 1 F_1 F1和 F 2 F_2 F2,然后 P 2 P_2 P2才去打开 F 1 F_1 F1(或 F 2 F_2 F2),由于文件 F 1 F_1 F1(或 F 2 F_2 F2)已经被打开,因此 P 2 P_2 P2会被阻塞。当 P 1 P_1 P1使用完 F 1 F_1 F1(或 F 2 F_2 F2),这时 P 2 P_2 P2才可以去打开 F 1 F_1 F1(或 F 2 F_2 F2),这样程序继续运行下去。
但是如果在 P 1 P_1 P1打开 F 1 F_1 F1的同时, P 2 P_2 P2去打开 F 2 F_2 F2,每个进程都占有一个打开的文件,此时就可能出现问题。因为当 P 1 P_1 P1试图去打开 F 2 F_2 F2,而 F 2 F_2 F2试图去打开 F 1 F_1 F1时,这两个进程都会因文件已被打开而阻塞,因此这两个进程将会无限期地等待下去,从而形成死锁。
6.1.2.2 竞争可消耗资源引起的死锁
如图所示, m 1 m_1 m1、 m 3 m_3 m3、 m 3 m_3 m3是可消耗资源。进程 P 1 P_1 P