死锁例证:哲学家就餐
Posted 2020.7.30
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了死锁例证:哲学家就餐相关的知识,希望对你有一定的参考价值。
由Edsger Dijkstra提出的哲学家就餐问题是一个经典的死锁例证。该问题的基本描述中是指定五个哲学家(本例中可以自由指定数目)。这些哲学家将花部分时间思考,花部分时间就餐。当他们思考时,不需要任何共享资源;但当他们就餐时,将使用有限的餐具。在问题的原始描述中,餐具是叉子,但在本例中,将使用筷子。很明显,哲学家就餐需要两根筷子。
问题中引入的难点是:作为哲学家,他们很穷,所以他们只能买五根筷子(更一般的讲,筷子和哲学家的数量相同)。他们围坐在桌子周围,每两人之间放一根筷子。当一个哲学家要就餐的时候,这个哲学家必须同时得到左边和右边的筷子。如果一个哲学家左边或右边的筷子已经有人在使用了,那么这个哲学家必须等待,直至可得到必需的筷子。
ponder参数用以设置思考和吃饭时长,如果有许多Philosopher,或者他们花费很多时间去思考,那么经管存在死锁的可能,但你可能永远看不到死锁。将ponder设置为0将倾向于使死锁尽快发生。
本人使用的判断所有任务是否全部挂起以此判断是否发生死锁,事实上毫无意义。你可以将ponder参数设为0,并使main()线程休眠一段时间,这样可能很快你就会看到死锁的发生。
//哲学家就餐
import java.util.concurrent.*;
import java.util.*;
import java.io.*;
class Chopstick
{
private boolean taken=false;
public synchronized void take(Philosopher th,String s) throws InterruptedException
{
if (taken == true) System.out.println(th + s + "已被人已被人占据");
else System.out.println(th + s + "成功获取");
while (taken)//如果已被他人占据,本人等待
{
th.wait=true;
wait();
}
taken=true;//被本人占据
}
public synchronized void drop(Philosopher[] p)
{
taken=false;
for(int i=0;i<p.length;i++)
p[i].wait=false;
notifyAll();//唤醒所有任务,至于某些任务是否能得到筷子,看速度
}
}
class Philosopher implements Runnable
{
private Chopstick left;
private Chopstick right;
private Philosopher[] p;
boolean wait=false;//判断当前任务是否被挂起
private final int id;
private final int ponderFactor;//暂停时间相关
private Random rand=new Random(47);
public Philosopher(Chopstick left,Chopstick right,int ident,int ponder,Philosopher[] p)
{
this.left=left;
this.right=right;
this.id=ident;
this.ponderFactor=ponder;
this.p=p;
}
private void pause() throws InterruptedException
{
if(ponderFactor==0)
return;
TimeUnit.MILLISECONDS.sleep(ponderFactor*250);
}
public void run()
{
try
{
while(!Thread.interrupted() )
{
System.out.println(this+" "+"思考一段时间 ");
pause();
System.out.print(this+" "+"尝试获取右筷子");
right.take(this,"右筷子");
System.out.print(this+" "+"尝试获取左筷子");
left.take(this,"左筷子");
System.out.println(this+" 吃饭一段时间 ");
pause();
right.drop(p);
left.drop(p);
}
}
catch(InterruptedException e)
{
System.out.println(this+"异常终止");
}
}
public String toString()
{
return " 哲学家:"+id+" ";
}
}
public class DeadLocking
{
public static void main(String []args) throws Exception
{
int ponder = 5;//随机数种子,用于给定思考和吃饭时间,0
int size = 5;//筷子数目,同样也是哲学家数目
Scanner scanf = new Scanner(System.in);
ponder = scanf.nextInt();
size = scanf.nextInt();
ExecutorService exec = Executors.newCachedThreadPool();
Chopstick[] chopsticks = new Chopstick[size];
for (int i = 0; i < chopsticks.length; i++)
chopsticks[i] = new Chopstick();
Philosopher[] philosophers = new Philosopher[size];
for (int i = 0; i < size; i++)
philosophers[i] = new Philosopher(chopsticks[i], chopsticks[(i + 1) % size], i, ponder,philosophers);
for (int i = 0; i < size; i++)
{
exec.execute(philosophers[i]);
}
// TimeUnit.SECONDS.sleep(5);
int k = 0;
while (k!= size)
{
k = 0;
for (int i = 0; i < size; i++)
{
if (philosophers[i].wait == true)
{
k++;
}
}
}
if(k==size)
{
System.out.println("死锁出现!!!!!!!!!");
exec.shutdownNow();
}
//exec.shutdownNow();
}
}
以上是关于死锁例证:哲学家就餐的主要内容,如果未能解决你的问题,请参考以下文章