关于哲学家就餐问题中wait()的运用,求大神解释。以下这些代码是对的还是错的?是不是解决了死锁问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于哲学家就餐问题中wait()的运用,求大神解释。以下这些代码是对的还是错的?是不是解决了死锁问题相关的知识,希望对你有一定的参考价值。
class Fork
private boolean taken=false;
synchronized void put()
taken=false;
notify();
synchronized void get()
throws InterruptedException
while (taken) wait();
taken=true;
class Philosopher extends Thread
private Fork left; private Fork right;
Philosopher(... Fork l, Fork r)
... left = l; right = r; ...
public void run()
try
while (true)
// thinking...
// hungry:
right.get(); left.get();
// eating...
// finished eating:
right.put(); left.put();
catch (InterruptedException e)
这里面一个线程会调用get()方法两次,分别去拿右边和左边的叉子,但是我总觉得这个代码有问题,当第一个线程第一次调用get()方法时会把taken值变成True,导致了这个线程在第二次调用get()方法去拿左边的叉子时进入wait状态从而没法拿左边的叉子。不知道自己的判断对不对,求解释!
死锁例证:哲学家就餐
由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();
以上是关于关于哲学家就餐问题中wait()的运用,求大神解释。以下这些代码是对的还是错的?是不是解决了死锁问题的主要内容,如果未能解决你的问题,请参考以下文章