问题描述:一圆桌前坐着5位哲学家,两个人中间有一只筷子,桌子中央有面条。哲学家思考问题,当饿了的时候拿起左右两只筷子吃饭,必须拿到两只筷子才能吃饭。上述问题会产生死锁的情况,当5个哲学家都拿起自己右手边的筷子,准备拿左手边的筷子时产生死锁现象。

解决办法:

1、添加一个服务生,只有当经过服务生同意之后才能拿筷子,服务生负责避免死锁发生。

2、每个哲学家必须确定自己左右手的筷子都可用的时候,才能同时拿起两只筷子进餐,吃完之后同时放下两只筷子。

3、规定每个哲学家拿筷子时必须拿序号小的那只,这样最后一位未拿到筷子的哲学家只剩下序号大的那只筷子,不能拿起,剩下的这只筷子就可以被其他哲学家使用,避免了死锁。这种情况不能很好的利用资源。 

代码实现:实现第2种方案

代码如下:
package cn.edu.sdust.Philosopher;

/*每个哲学家相当于一个线程*/
class Philosopher extends Thread{
    private String name;
    private Fork fork;
    public Philosopher(String name,Fork fork){
        super(name);
        this.name=name;
        this.fork=fork;
    }

public void run(){
        while(true){
            thinking();
            fork.takeFork();
            eating();
            fork.putFork();
        }

}

public void eating(){
        System.out.println("I am Eating:"+name);
        try {
            sleep(1000);//模拟吃饭,占用一段时间资源
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

public void thinking(){
        System.out.println("I am Thinking:"+name);
        try {
            sleep(1000);//模拟思考
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

class Fork{
    /*5只筷子,初始为都未被用*/
    private boolean[] used={false,false,false,false,false,false};

/*只有当左右手的筷子都未被使用时,才允许获取筷子,且必须同时获取左右手筷子*/
    public synchronized void takeFork(){
        String name = Thread.currentThread().getName();
        int i = Integer.parseInt(name);
        while(used[i]||used[(i+1)%5]){
            try {
                wait();//如果左右手有一只正被使用,等待
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        used[i ]= true;
        used[(i+1)%5]=true;
    }

/*必须同时释放左右手的筷子*/
    public synchronized void putFork(){
        String name = Thread.currentThread().getName();
        int i = Integer.parseInt(name);

used[i ]= false;
        used[(i+1)%5]=false;
        notifyAll();//唤醒其他线程
    }
}

//测试
public class ThreadTest {

public static void main(String []args){
        Fork fork = new Fork();
        new Philosopher("0",fork).start();
        new Philosopher("1",fork).start();
        new Philosopher("2",fork).start();
        new Philosopher("3",fork).start();
        new Philosopher("4",fork).start();
    }
}

运行结果:

代码如下:
I am Thinking:0
I am Thinking:2
I am Thinking:3
I am Thinking:1
I am Thinking:4
I am Eating:0
I am Eating:2
I am Thinking:0
I am Eating:4
I am Thinking:2
I am Eating:1
I am Thinking:4
I am Eating:3
I am Thinking:1
I am Eating:0
I am Thinking:3
I am Eating:2
I am Thinking:0
I am Eating:4
I am Thinking:2

分析:上述解决方案解决了死锁问题。可以看到最多只能有两条相邻的eating结果,因为每个时刻最多能够满足两个人同时进餐,且两人座位不相邻。

Java多线程,哲学家就餐问题的更多相关文章

  1. JAVA多线程学习--哲学家就餐问题

    哲学家就餐问题是1965年由Dijkstra提出的一种线程同步的问题. 问题描述:一圆桌前坐着5位哲学家,两个人中间有一只筷子,桌子中央有面条.哲学家思考问题,当饿了的时候拿起左右两只筷子吃饭,必须拿 ...

  2. JAVA并发,经典死锁案例-哲学家就餐

    转自:http://blog.csdn.net/tayanxunhua/article/details/38691005 死锁经典案例:哲学家就餐. 这个案例会导致死锁. 通过修改<Java编程 ...

  3. 哲学家就餐问题-Java语言实现死锁避免

    哲学家就餐问题-Java语言实现死锁避免 我死锁预防是至少破坏死锁产生的四个必要条件之一,带来的问题就是系统资源利用率低且不符合开发习惯,而死锁避免不是事先釆取某种限制措施破坏死锁的必要条件,只是注意 ...

  4. linux下多线程互斥量实现生产者--消费者问题和哲学家就餐问题

    生产者消费者问题,又有界缓冲区问题.两个进程共享一个一个公共的固定大小的缓冲区.其中一个是生产者,将信息放入缓冲区,另一个是消费者,从缓冲区中取信息. 问题的关键在于缓冲区已满,而此时生产者还想往其中 ...

  5. 50个Java多线程面试题

    不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题.Java 语言一个重要的特点就是内置了对并发的支持,让 Java 大受企业和程序员的欢迎.大多数待遇丰厚的 Java 开发职位都要求开发者 ...

  6. 50个Java多线程面试题(上)

    Java 语言一个重要的特点就是内置了对并发的支持,让 Java 大受企业和程序员的欢迎.大多数待遇丰厚的 Java 开发职位都要求开发者精通多线程技术并且有丰富的 Java 程序开发.调试.优化经验 ...

  7. java多线程(八)-死锁问题和java多线程总结

    为了防止对共享受限资源的争夺,我们可以通过synchronized等方式来加锁,这个时候该线程就处于阻塞状态,设想这样一种情况,线程A等着线程B完成后才能执行,而线程B又等着线程C,而线程C又等着线程 ...

  8. java多线程总结(二)

    线程一般有6个状态: 新建状态:NEW 可运行状态:RUNNABLE 休眠状态:TIMED_WAITING 等待状态:WAITING 阻塞状态:BLOCKED 终止状态“TERMINATED 当我们使 ...

  9. java多线程面试题(来自转载)

    在典型的Java面试中, 面试官会从线程的基本概念问起, 如:为什么你需要使用线程, 如何创建线程,用什么方式创建线程比较好(比如:继承thread类还是调用Runnable接口),然后逐渐问到并发问 ...

  10. Java多线程与并发基础

    CS-LogN思维导图:记录专业基础 面试题 开源地址:https://github.com/FISHers6/CS-LogN 多线程与并发基础 实现多线程 面试题1:有几种实现线程的方法,分别是什么 ...

随机推荐

  1. 控制器view加载

    出自李明杰讲课视频

  2. thinkphp路径引用问题

    查看ThinkPHP\Library\Behavior\ContentReplaceBehavior.class文件,常量定义如下定义: '__ROOT__'      =>  __ROOT__ ...

  3. Mac下修改Mysql密码

    1. 停止Mysql 2. cd /usr/local/mysql/bin/ 3. 使用跳过权限方式启动mysql sudo ./mysqld_safe --skip-grant-tables &am ...

  4. linux源码“.config”文件分析

    一..config文件概述 .config文件是linux内核配置文件,当执行#make uImage编译生成内核时,顶层的Makefile会读取.config文件的内容,根据这个配置文件来编译所定制 ...

  5. Lambda表达式, 可以让我们的代码更优雅.

    在C#中, 适当地使用Lambda表达式, 可以让我们的代码更优雅. 通过lambda表达式, 我们可以很方便地创建一个delegate: 下面两个语句是等价的 Code highlighting p ...

  6. 【转】TypeScript中文入门教程

    目录 虽然我是转载的,但看在Copy这么多文章也是很幸苦的好吧,我罗列一个目录. 转载:<TypeScript 中文入门教程> 17.注解 (2015-12-03 11:36) 转载:&l ...

  7. hadoop 2.x 安装包目录结构分析

    bin:Hadoop最基本的管理脚本和使用脚本所在目录,这些脚本是sbin目录下管理脚本的基础实现,用户可以直接使用这些脚本管理和使用hadoop etc:Hadoop配置文件所在目录,包括core- ...

  8. HJA的异或值

    HJA的异或值 查看 提交 统计 提问 总时间限制:  20000ms 内存限制:  512000kB 描述 形态形成场(Morphogenetic Field)假说是Rupert Sheldrake ...

  9. latch free

    latch free 等待事件: latch: cache buffers chains 这个等待事件其实还有另外一个重要的原因,那么就是逻辑读太高,SQL执行计划走错了导致的. 当进程想要获取锁存器 ...

  10. windows/NBTSTAT,linux/nmblookup命令详解,查询NetBIOS名

    NBTSTAT命令详解 请问: Linux下有没有和nbtstat一样的命令,用 nmblookup -A ip 可以 nbstat命令主要用于查看当前基于netbios的tcp/ip连接状态,通过该 ...