开始的情境 所以问题就产生了: 哲学家0拿起了左手边的筷子0,想去拿右手边的筷子1,拿不到就等着哲学家1拿起了左手边的筷子1,想去拿右手边的筷子2,拿不到就等着哲学家2拿起了左手边的筷子2,想去拿右手边的筷子3,拿不到就等着哲学家3拿起了左手边的筷子3,想去拿右手边的筷子4,拿不到就等着哲学家4拿起了左手边的筷子4,想去拿右手边的筷子0,拿不到就等着
大家都在挨饿,永远都拿不到右边的筷子 2、修改一下,哲学家拿起了左手边的筷子,检查右手边的是否能拿到,如果不能就放下左手边的筷子,这样就会产生饥饿问题——大家都把筷子放下了… 解决方案之一: 设置哲学家边上有一个侍者,哲学家[i]想吃的时候去问问侍者,侍者看一下筷子i和筷子(i+1) % N是不是有被用的,没有被用的就让哲学家[i]去吃饭,有被用的就让哲学家等着[进入等待队列]。用synchronized控制某一个时刻必须只能有一个哲学家去问侍者。 代码: package com.sdkd.hms;/** * Created by hms on 2017/3/19. */package com.sdkd.hms;/** * Created by hms on 2017/3/19. */class Philosopher extends Thread{ private int i; private Waiter waiter; public Philosopher(int i, Waiter waiter) { this.i = i; this.waiter = waiter; } @Override public void run() { hungry(); synchronized (waiter) { waiter.take_forks(i); } eat(); synchronized (waiter) { waiter.put_forks(i); } thinking(); } public void eat() { System.out.println('Thread ' + i + ' ' + '开始吃东西!'); try { Thread.sleep(3 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } } public void thinking() { System.out.println('Thread ' + i + ' ' + ' ' + '开始思考。。。'); try { Thread.sleep(1 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } } public void hungry() { System.out.println('Thread ' + i + ' ' + ' ' + '在挨饿!'); try { Thread.sleep(1 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } }}class Waiter { public static int N = 5; private boolean used[] = new boolean[N]; public void take_forks(int i) { while (used[i] || used[(i+1) % N]){ try { System.out.println('Thread ' + i + ' ' + '得到问侍者的机会' + ' ' + '但是边上的筷子被用了,不能吃 ' + '还没问侍者的线程可以问侍者了' + ' ' + 'Thread' + ' ' + i + ' ' + '进入等待队列'); wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println('Thread ' + i + ' ' + '得到问侍者的机会' + ' ' + '并且拿到了筷子!' + ' 筷子 ' + i + ' 和' + ' 筷子' + ' ' + ((i+1) % N )+ ' 被拿起来了' + ' 然后Thread ' + i + ' ' + '准备吃饭了'); used[i] = true; used[(i+1) % N] = true; } public void put_forks(int i) { used[i] = false; used[(i+1) % N] = false; System.out.println('筷子 ' + i + ' 和' + ' 筷子' + ' ' + ((i+1) % N )+ ' 被放下了' + ' 然后Thread' + ' ' + i + ' 准备思考了'); notify(); }}public class Client { public static void main(String[] args) { Waiter waiter = new Waiter(); for(int i = 0; i < waiter.n;="" ++i)="" {="" philosopher="" philosopher="">new Philosopher(i, waiter); philosopher.start(); } }}
/**OutoutThread 0 在挨饿!Thread 1 在挨饿!Thread 2 在挨饿!Thread 3 在挨饿!Thread 4 在挨饿!Thread 0 得到问侍者的机会 并且拿到了筷子! 筷子 0 和 筷子 1 被拿起来了 然后Thread 0 准备吃饭了Thread 0 开始吃东西!Thread 1 得到问侍者的机会 但是边上的筷子被用了,不能吃 还没问侍者的线程可以问侍者了 Thread 1 进入等待队列Thread 2 得到问侍者的机会 并且拿到了筷子! 筷子 2 和 筷子 3 被拿起来了 然后Thread 2 准备吃饭了Thread 2 开始吃东西!Thread 3 得到问侍者的机会 但是边上的筷子被用了,不能吃 还没问侍者的线程可以问侍者了 Thread 3 进入等待队列Thread 4 得到问侍者的机会 但是边上的筷子被用了,不能吃 还没问侍者的线程可以问侍者了 Thread 4 进入等待队列筷子 0 和 筷子 1 被放下了 然后Thread 0 准备思考了Thread 0 开始思考。。。Thread 1 得到问侍者的机会 但是边上的筷子被用了,不能吃 还没问侍者的线程可以问侍者了 Thread 1 进入等待队列筷子 2 和 筷子 3 被放下了 然后Thread 2 准备思考了Thread 2 开始思考。。。Thread 3 得到问侍者的机会 并且拿到了筷子! 筷子 3 和 筷子 4 被拿起来了 然后Thread 3 准备吃饭了Thread 3 开始吃东西!筷子 3 和 筷子 4 被放下了 然后Thread 3 准备思考了Thread 3 开始思考。。。Thread 4 得到问侍者的机会 并且拿到了筷子! 筷子 4 和 筷子 0 被拿起来了 然后Thread 4 准备吃饭了Thread 4 开始吃东西!筷子 4 和 筷子 0 被放下了 然后Thread 4 准备思考了Thread 4 开始思考。。。Thread 1 得到问侍者的机会 并且拿到了筷子! 筷子 1 和 筷子 2 被拿起来了 然后Thread 1 准备吃饭了Thread 1 开始吃东西!筷子 1 和 筷子 2 被放下了 然后Thread 1 准备思考了Thread 1 开始思考。。。*/
这个输出完美的解释了上面提到的解决方案,具体的自己领会吧~全说了也没意思了~ |
|