java 死锁问题分析
程序员文章站
2022-04-18 14:37:40
...
1,概念理解
通俗的说,死锁是一种线程或者进程运行卡顿或者说没反应的现象,一般由于资源互斥且循环依赖导致的。
死锁经典问题,一是银行家算法,二是哲学家就餐。
2,银行家算法分析
银行家算法种,状态安全判断算法,是去寻找一个比可用资源少的最多还需要资源量的线程,以便于回收资源,进行下一轮循环。
这个过程就需要O(n),而除去当前的线程,还剩n-1。也就是说,需要(n-1)O(n)。
因为资源有多种,希望通过排序来简化的思路是不行的,这就类似背包问题,还是一个NP难。
采用蛮力算法,最坏就是(n-1)!。
3,哲学家就餐算法分析
解决办法是添加了假设条件。假设每位哲学家如果没有拿到两只筷子就放弃手头的一只,此举打破了死锁必要条件中的请求和保持。
4,哲学家就餐代码实现
package com.csm.current.thread.share;
import java.util.concurrent.locks.ReentrantLock;
/**
* 哲学家就餐问题
* 产生死锁程序
*/
public class Test05 {
public static void main(String[] args) {
Chopstick c1 = new Chopstick("1");
Chopstick c2 = new Chopstick("2");
Chopstick c3 = new Chopstick("3");
Chopstick c4 = new Chopstick("4");
Chopstick c5 = new Chopstick("5");
new Pjilosopher("csm1",c1,c2).start();
new Pjilosopher("csm2",c2,c3).start();
new Pjilosopher("csm3",c3,c4).start();
new Pjilosopher("csm4",c4,c5).start();
new Pjilosopher("csm5",c5,c1).start();
}
}
class Pjilosopher extends Thread {
Chopstick left;
Chopstick right;
public Pjilosopher(String name, Chopstick left, Chopstick right) {
super(name);
this.left = left;
this.right = right;
}
// @Override
// public void run() {
// while (true) {
// synchronized (left) {
// synchronized (right) {
// eat();
// }
// }
// }
// }
@Override
public void run() {
while (true){
if(left.tryLock()){
try {
if(right.tryLock()){
try {
eat();
}finally {
right.unlock();
}
}
}finally {
left.unlock();
}
}
}
}
private void eat() {
System.out.println("eat 10");
}
}
class Chopstick extends ReentrantLock {
String name;
public Chopstick(String name) {
this.name = name;
}
@Override
public String toString() {
return "Chopstick{" +
"name='" + name + '\'' +
'}';
}
}
5,死锁问题应对方案
(1)死锁预防。打破死锁产生的四个必要条件
(2)死锁检测。依赖循环检测。
(3)鸵鸟算法。当作没看见,重启系统。