死锁例证:哲学家就餐

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();
    


以上是关于死锁例证:哲学家就餐的主要内容,如果未能解决你的问题,请参考以下文章

死锁例证:哲学家就餐

死锁例证:哲学家就餐

哲学家就餐问题与死锁总结

从哲学家就餐问题彻底认识死锁

JUC并发编程 活跃性 -- 死锁 & 定位死锁 & 哲学家就餐问题

Thking in Java---从哲学家就餐问题看死锁现象