死锁
- 1. 死锁的成因
- 2. 解决方案
1. 死锁的成因
- 互斥条件: 一个资源每次只能被一个进程使用。
- 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
- 不可剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
- 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四条是死锁产生的必要条件, 缺一不可, 所以我们可以破坏上述条件来避免死锁的产生
2. 解决方案
死锁的三种典型情况:
- 一个线程一把锁, 但是是不可重入锁, 该线程连续两次加锁.
- 两个线程两把锁, 这两个线程先分别获取一把锁, 然后尝试获取对方的锁.
- M个线程N把锁.
M个线程N把锁最典型的例子就是 “哲学家进餐问题” 这也是操作系统中的一个典型案例.
如上图所示, 总共有五位哲学家和五根筷子, 每位哲学家会做两件事: 思考和吃饭.
每个哲学家吃饭的时间都不固定, 并且当他们拿起一根筷子就算获取不到另外一根筷子也不会放弃手里的这根筷子, 这时如果五位哲学家同时想要吃东西, 并且同时获取了左边的筷子, 此时就会产生死锁.
我们想要解决死锁的问题就可以从上边那四个成因入手, 但是由于 “互斥条件” 和 “不可剥夺条件” 是锁的特性无法改变所以只能从 “请求与保持条件” 和 “循环等待条件” 入手.
我们可以通过给锁编号, 并且规定加锁的顺序来避免死锁, 例如 把筷子分为 1 到 5 号让每个人在拿筷子时先拿编号小的在拿编号大的
这时五号筷子就会空闲然后被最上边的那个人获取到, 当他吃完放下筷子时其他哲学家就可以依次进餐, 这样就避免了死锁.
还可以给哲学家编号让奇数号的哲学家先拿左边的筷子, 偶数号的哲学家先拿右边的筷子这样也可以避免死锁.
“银行家算法” 是一个著名的避免死锁的算法, 但是由于太过于复杂工作中很少用到这里就不在解释.