分享

利用synchronized解决哲学家问题

 yespon 2017-03-19


大家可以把其他的解法都列举一下,别的思路或者同一思路都可以。但是,请给出你的代码[talk is cheap ,show us you code ].网上能搜到的都是前几年的,高质量的程序员确实越来越少…2333

开始的情境
1、N[本文假设N=5]个哲学家们都在着一个桌子挨饿,桌子中间有好吃的面条 。
2、哲学家两边各有一只筷子。哲学家[i]左手边筷子编号为i,右手边编号为(i+1)%N
3、哲学家只能拿紧挨着自己的两边的筷子
如图:[图片来自网络]
来自

所以问题就产生了:
1、如果哲学家同时去拿筷子,可能就会导致死锁。

哲学家0拿起了左手边的筷子0,想去拿右手边的筷子1,拿不到就等着哲学家1拿起了左手边的筷子1,想去拿右手边的筷子2,拿不到就等着哲学家2拿起了左手边的筷子2,想去拿右手边的筷子3,拿不到就等着哲学家3拿起了左手边的筷子3,想去拿右手边的筷子4,拿不到就等着哲学家4拿起了左手边的筷子4,想去拿右手边的筷子0,拿不到就等着
  • 1
  • 2
  • 3
  • 4
  • 5

大家都在挨饿,永远都拿不到右边的筷子

2、修改一下,哲学家拿起了左手边的筷子,检查右手边的是否能拿到,如果不能就放下左手边的筷子,这样就会产生饥饿问题——大家都把筷子放下了…

解决方案之一:

设置哲学家边上有一个侍者,哲学家[i]想吃的时候去问问侍者,侍者看一下筷子i和筷子(i+1) % N是不是有被用的,没有被用的就让哲学家[i]去吃饭,有被用的就让哲学家等着[进入等待队列]。用synchronized控制某一个时刻必须只能有一个哲学家去问侍者。
一旦当某一个哲学家吃完了,它就会跟侍者说一声,然后侍者跟等待队列里的哲学家喊一声:有人吃完了,你们要不要来试试看能不能吃饭!这个时候等待队列里的哲学家就会冲上去问侍者[顺序由操作系统控制],然后侍者看一下哲学家[i]的情况是否允许,允许就让哲学家吃饭,不行就让他再等着。

代码:

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(); } }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
/**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 开始思考。。。*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

这个输出完美的解释了上面提到的解决方案,具体的自己领会吧~全说了也没意思了~

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多