美文网首页
哲学家进餐问题

哲学家进餐问题

作者: Stringer | 来源:发表于2016-12-16 17:55 被阅读64次

1965年,荷兰计算机科学家图灵奖得主Edsger Wybe Dijkstra提出并解决了一个他称之为哲学家进餐的同步问题。这个问题可以简单地描述如下:五个哲学家围坐在一张圆桌周围,每个哲学家面前都有一盘通心粉。由于通心粉很滑,所以需要两把叉子才能夹住。相邻两个盘子之间放有一把叉子如下图所示。哲学家的生活中有两种交替活动时段:即吃饭和思考。当一个哲学家觉得饿了时,他就试图分两次去取其左边和右边的叉子,每次拿一把,但不分次序。如果成功地得到了两把叉子,就开始吃饭,吃完后放下叉子继续思考。   把上面问题中的哲学家换成线程,把叉子换成竞争的临界资源,上面的问题就是线程竞争资源的问题。如果没有经过精心的设计,系统就会出现死锁、活锁、吞吐量下降等问题

Paste_Image.png
package threadTest;

import java.util.concurrent.Semaphore;

public class test01 {
     public static void main(String[] args) {
            String[] names = { "骆昊", "王大锤", "张三丰", "杨过", "李莫愁" };   // 5位哲学家的名字
//        ExecutorService es = Executors.newFixedThreadPool(AppContext.NUM_OF_PHILO); // 创建固定大小的线程池
//        for(int i = 0, len = names.length; i < len; ++i) {
//            es.execute(new Philosopher(i, names[i]));   // 启动线程
//        }
//        es.shutdown();
            for(int i = 0, len = names.length; i < len; ++i) {
                new Thread(new Philosopher(i, names[i])).start();
            }
        }
}

class AppContext{
    public static final int NUM_OF_FORKS=5; //叉子数量(资源)
    public static final int NUM_OF_PHILO=5; //哲学家数量(线程)
    
    public static Semaphore[] forks;    //叉子的信号量
    public static Semaphore counter;    //哲学家的信号量

    static{
        forks=new Semaphore[NUM_OF_FORKS];
        
        for(int i=0,len=forks.length;i<len;i++){
            forks[i]=new Semaphore(1);  //每个叉子的信号量为1
        }
        
        counter=new Semaphore(NUM_OF_PHILO-1);  //如果有n个哲学家,最多只允许n-1人同时取叉子
    }
    
    /**
     * 取得叉子
     * @param index 第几个哲学家
     * @param leftFirst 是否先取得左边的叉子
     * @throws InterruptedException
     */
    public static void putOnFork(int index,boolean leftFirst)throws InterruptedException{
        if(leftFirst){
            forks[index].acquire();
            forks[(index+1)%NUM_OF_PHILO].acquire();
        }else{
            forks[(index+1)%NUM_OF_PHILO].acquire();
            forks[index].acquire();
        }
        
    }
    
    /**
     * 放回叉子
     * @param index 第几个哲学家
     * @param leftFirst 是否先放回左边的叉子
     * @throws InterruptedException
     */
    public static void putDownFork(int index,boolean leftFirst)throws InterruptedException{
        if(leftFirst){
            forks[index].release();
            forks[(index+1)%NUM_OF_PHILO].release();
        }else{
            forks[(index+1)%NUM_OF_PHILO].release();
            forks[index].release();
        }
        
    }
    
}

/**
 * 哲学家
 *
 */
class Philosopher implements Runnable {
    private int index;      // 编号
    private String name;    // 名字

    public Philosopher(int index, String name) {
        this.index = index;
        this.name = name;
    }
    @Override
    public void run() {
        while(true) {
            try {
                AppContext.counter.acquire();
                boolean leftFirst = index % 2 == 0;
                AppContext.putOnFork(index, leftFirst);
                System.out.println(name + "正在吃意大利面(通心粉)...");   // 取到两个叉子就可以进食
                AppContext.putDownFork(index, leftFirst);
                AppContext.counter.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}











相关文章

  • 哲学家进餐问题

    1965年,荷兰计算机科学家图灵奖得主Edsger Wybe Dijkstra提出并解决了一个他称之为哲学家进餐的...

  • 哲学家进餐问题

    问题描述 一张圆桌旁坐了五个哲学家,每两名哲学家中间有一根筷子,每个哲学家面前有一碗米饭。哲学家重复的做思考和进餐...

  • 哲学家进餐问题

    哲学家进餐问题是著名的死锁问题,5个哲学家,5根筷子,每个哲学家进餐需要获得左右两根筷子才可以; 信号量 使用信号...

  • 经典PIC问题

    哲学家进餐: 哲学家问题可出现拿起左边的筷子,然后拿起右边的筷子进餐,但是假如五个哲学家同时拿起左边的筷子,那么右...

  • 哲学家进餐

    哲学家进餐 VC++相关演示,本源码演示了线程同步算法的哲学家进餐问题,说明:本程序是操作系统中比较典型的线程同步...

  • windows下 c 实现哲学家进餐问题

  • 【专项专攻】01-哲学家进餐问题

    前言: 当一位哲学家思考时,他与其他同事不交流。时而,他会感到饥饿,并试图拿起与他相近的两根筷子(筷子在他和他的左...

  • Java 死锁分类

    1. 死锁简介 经典的“哲学家进餐”问题很好的描述了死锁的情况。5个哲学家吃中餐,坐在一张圆桌上,有5根筷子,每个...

  • 线程同步导致的问题死锁哲学家进餐问题

    请关注我的微信公众号 个人微信公众号 技术交流群 (仅作技术交流):642646237 ​请关注我的头条号: 线程...

  • 8.2 经典进程同步问题-哲学家进餐问题

    问题描述 一张圆桌上坐着5名哲学家,每两个哲学家之间的桌上摆一根筷子,桌子的中间是一碗米饭。哲学家们倾注毕生精力用...

网友评论

      本文标题:哲学家进餐问题

      本文链接:https://www.haomeiwen.com/subject/gawgmttx.html