Thread.join() 在 Dining Philosophers 实现中无法正常工作
Posted
技术标签:
【中文标题】Thread.join() 在 Dining Philosophers 实现中无法正常工作【英文标题】:Thread.join() is not working at expect in Dining Philosophers implementation 【发布时间】:2018-09-05 01:21:16 【问题描述】:我已经使用 Java 中的 Monitor (Synchronized) 实现了餐饮哲学家问题。
这个计划的目标是:
每个哲学家都应该遵循思考、拿筷子、吃饭、放筷子的工作流程(无竞赛条件)。
无死锁
我认为这段代码似乎工作正常,但有些地方不对,因为它永远运行我试图调试它,调试工具停在这一行哲学家[i].t.join();但程序并未终止。
请帮助我找出问题或告诉我如何解决它。 谢谢你的建议。
MyMonitor 类:
class MyMonitor
private enum States THINKING, HUNGRY, EATING;
private States[] state;
public MyMonitor()
state = new States[5];
for(int i = 0; i < 5; i++)
state[i] = States.THINKING;
System.out.println("Philosopher " + i + " is THINKING");
private void test(int i)
if((state[(i+4)%5]!=States.EATING) && (state[i]==States.HUNGRY) && (state[(i+1)%5]!=States.EATING))
state[i] = States.EATING;
System.out.println("Philosopher " + i + " is EATING");
notify();
public synchronized void pickup(int i)
state[i] = States.HUNGRY;
System.out.println("Philosopher " + i + " is HUNGRY");
test(i);
if (state[i] != States.EATING)
System.out.println("Philosopher " + i + " is WAITING");
try
wait();
catch (InterruptedException e)
e.printStackTrace();
public synchronized void putdown(int i)
state[i] = States.THINKING;
System.out.println("Philosopher " + i + " is THINKING");
test((i+4)%5);
test((i+1)%5);
MyPhilosopher 类:
class MyPhilosopher implements Runnable
private int myID;
private int eatNum;
private MyMonitor monitor;
private Thread t;
public MyPhilosopher(int myID, int eatNum, MyMonitor monitor)
this.myID = myID;
this.eatNum = eatNum;
this.monitor = monitor;
t = new Thread(this);
t.start();
public void run()
int count = 1;
while(count <= eatNum )
monitor.pickup(myID);
try
Thread.sleep(1000);
catch (InterruptedException e)
e.printStackTrace();
monitor.putdown(myID);
try
Thread.sleep(1000);
catch (InterruptedException e)
e.printStackTrace();
count++;
public static void main(String[] args)
int eatNum = 10;
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println("xxx");
System.out.println("xxx");
System.out.println("xxx");
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println("Starting");
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println("");
MyMonitor monitor = new MyMonitor();
MyPhilosopher[] philosopher = new MyPhilosopher[5];
for(int i = 0; i < 5; i++)
philosopher[i] = new MyPhilosopher(i, eatNum, monitor);
for(int i = 0; i < 5; i++)
try
philosopher[i].t.join();
catch (InterruptedException e)
e.printStackTrace();
System.out.println("----------------------------------------------------------------------------------------------------");
System.out.println("Ended");
【问题讨论】:
当您在调试器中时,您可以查看所有应用程序线程。每个 IDE 都可以在运行的线程之间显示和切换。那时你很有可能会发现死锁。 【参考方案1】:我已经执行了您的代码,并且它运行良好,直到执行两次或多次。此外,您可以减少睡眠时间,您的代码正确但完美,直到 4 个 pilosopher 正在等待并且其中一个正在吃饭。我不喜欢它。你打破了一个科夫曼条件,但我建议你使用其他实现,比如打破保持和等待条件。我的意思是,你可以两根筷子都拿,也可以不拿,其他的实现可以是,偶数的 pilosophers 拿右边的筷子,奇数的 pilosophers 拿左边的筷子。祝你好运!
Philosopher 4 is THINKING
Philosopher 0 is EATING
Philosopher 3 is HUNGRY
Philosopher 3 is WAITING
Philosopher 1 is HUNGRY
Philosopher 1 is WAITING
Philosopher 2 is THINKING
Philosopher 3 is EATING
Philosopher 0 is THINKING
Philosopher 1 is EATING
Philosopher 4 is HUNGRY
Philosopher 4 is WAITING
Philosopher 3 is THINKING
Philosopher 4 is EATING
Philosopher 2 is HUNGRY
Philosopher 2 is WAITING
Philosopher 0 is HUNGRY
Philosopher 0 is WAITING
Philosopher 1 is THINKING
Philosopher 2 is EATING
Philosopher 4 is THINKING
Philosopher 0 is EATING
Philosopher 3 is HUNGRY
Philosopher 3 is WAITING
Philosopher 2 is THINKING
Philosopher 3 is EATING
Philosopher 1 is HUNGRY
Philosopher 1 is WAITING
Philosopher 0 is THINKING
Philosopher 1 is EATING
Philosopher 4 is HUNGRY
Philosopher 4 is WAITING
Philosopher 3 is THINKING
Philosopher 4 is EATING
Philosopher 2 is HUNGRY
Philosopher 2 is WAITING
Philosopher 0 is HUNGRY
Philosopher 0 is WAITING
Philosopher 1 is THINKING
Philosopher 2 is EATING
Philosopher 3 is HUNGRY
Philosopher 3 is WAITING
Philosopher 4 is THINKING
Philosopher 0 is EATING
Philosopher 2 is THINKING
Philosopher 3 is EATING
Philosopher 1 is HUNGRY
Philosopher 1 is WAITING
Philosopher 4 is HUNGRY
Philosopher 4 is WAITING
Philosopher 0 is THINKING
Philosopher 1 is EATING
Philosopher 2 is HUNGRY
Philosopher 2 is WAITING
Philosopher 3 is THINKING
Philosopher 4 is EATING
Philosopher 1 is THINKING
Philosopher 2 is EATING
Philosopher 0 is HUNGRY
Philosopher 0 is WAITING
Philosopher 4 is THINKING
Philosopher 0 is EATING
Philosopher 3 is HUNGRY
Philosopher 3 is WAITING
Philosopher 2 is THINKING
Philosopher 3 is EATING
Philosopher 1 is HUNGRY
Philosopher 1 is WAITING
Philosopher 4 is HUNGRY
Philosopher 4 is WAITING
Philosopher 0 is THINKING
Philosopher 1 is EATING
Philosopher 2 is HUNGRY
Philosopher 2 is WAITING
Philosopher 3 is THINKING
Philosopher 4 is EATING
Philosopher 0 is HUNGRY
Philosopher 0 is WAITING
Philosopher 1 is THINKING
Philosopher 2 is EATING
Philosopher 4 is THINKING
Philosopher 0 is EATING
Philosopher 2 is THINKING
Philosopher 1 is HUNGRY
Philosopher 1 is WAITING
Philosopher 0 is THINKING
Philosopher 1 is EATING
Philosopher 1 is THINKING
----------------------------------------------------------------------------------------------------
Ended
但是,我已经检查过您是否在某些特殊情况下出现了死锁,例如: 当所有的哲学家至少有一个可以吃饭而其他人都在等待时。但是我已经通过在函数的标头中使用同步更改了测试中的代码,通过 while 和在方法 putdown() 中使用了 test() 方法的 if 条件,我通过 notifyAll() 更改了通知; 代码是这样的:
class MyMonitor
private enum States THINKING, HUNGRY, EATING;
private States[] state;
public MyMonitor()
state = new States[5];
for(int i = 0; i < 5; i++)
state[i] = States.THINKING;
System.out.println("Philosopher " + i + " is THINKING");
private synchronized void test(int i)
while((state[(i+4)%5]!=States.EATING) && (state[i]==States.HUNGRY) && (state[(i+1)%5]!=States.EATING))
state[i] = States.EATING;
System.out.println("Philosopher " + i + " is EATING");
// notify();
public synchronized void pickup(int i)
state[i] = States.HUNGRY;
System.out.println("Philosopher " + i + " is HUNGRY");
test(i);
if (state[i] != States.EATING)
System.out.println("Philosopher " + i + " is WAITING");
try
wait();
catch (InterruptedException e)
e.printStackTrace();
public synchronized void putdown(int i)
state[i] = States.THINKING;
System.out.println("Philosopher " + i + " is THINKING");
//test((i+4)%5);
//test((i+1)%5);
notifyAll();
我建议您使用一个或多个实现,然后再考虑要打破什么科夫曼条件。祝你好运
【讨论】:
以上是关于Thread.join() 在 Dining Philosophers 实现中无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章
std::thread::join 无限期地阻塞在 main 之外
在 JRuby 分析中花费大量时间在 Thread#initialize 和 Thread#join 中意味着啥?