多线程系列之哲学家进餐

晚上学习了多线程的知识,总结了哲学家进餐问题,分享给大家.

 

  1 package thread;
  2 
  3 import java.util.Random;
  4 // 哲学家进餐问题
  5 
  6 /* 同时满足以下四个条件时,就会发生死锁
  7  * 1. 互斥条件:线程使用的资源中至少有一个是不能共享的.这里,一根筷子一次就只能
  8  *    被一个哲学家使用.
  9  * 2. 至少有一个线程持有一个资源,并且它在等待获取一个当前被别的线程持有的资源.也就是
 10  *    说,要放生死锁,哲学家必须拿着一根筷子并且等待另一根.
 11  * 3. 资源不能被进程(线程)抢占.所有的进程必须把资源释放作为普通条件.哲学家很有礼貌,
 12  *    不会从其他哲学家那里抢筷子.
 13  * 4. 必须有循环等待,这时,一个进程等待其他进程持有的资源,后者又在等待另外一个进程持有的
 14  *    资源,这样一直下去,直到有一个进程在等待第一个进程(线程)持有的资源,使得大家都被锁住.
 15  *    在这里,以为每个哲学家都试图先得到左边的筷子,然后得到右边的筷子,所以发生了循环等待.
 16  *    在下面的例子中,针对最后一个哲学家,通过交换构造器中的初始化顺序,打破了死锁条件,使得
 17  *    最后一个哲学家先拿右边的筷子,再拿左边的筷子.
 18  */
 19 class Chopstick {
 20     private static int counter = 0;
 21     private int number = counter++;
 22 
 23     public String toString() {
 24         return "Chopstick " + number;
 25     }
 26 }
 27 
 28 class Philosopher extends Thread {
 29     private static Random rand = new Random();
 30     private static int counter = 0;
 31     private int number = counter++;
 32     private Chopstick leftChopstick;
 33     private Chopstick rightChopstick;
 34     static int ponder = 0; // Package access
 35 
 36     public Philosopher(Chopstick left, Chopstick right) {
 37         leftChopstick = left;
 38         rightChopstick = right;
 39         start();
 40     }
 41 
 42     public void think() {
 43         System.out.println(this + " thinking");
 44         if (ponder > 0)
 45             try {
 46                 sleep(rand.nextInt(ponder));
 47             } catch (InterruptedException e) {
 48                 throw new RuntimeException(e);
 49             }
 50     }
 51 
 52     public void eat() {
 53         synchronized (leftChopstick) {
 54             System.out.println(this + " has " + this.leftChopstick
 55                     + " Waiting for " + this.rightChopstick);
 56             synchronized (rightChopstick) {
 57                 System.out.println(this + " eating");
 58             }
 59         }
 60     }
 61 
 62     public String toString() {
 63         return "Philosopher " + number;
 64     }
 65 
 66     public void run() {
 67         while (true) {
 68             think();
 69             eat();
 70         }
 71     }
 72 }
 73 
 74 public class DiningPhilosophers {
 75     public static void main(String[] args) {
 76         args = new String[4];
 77         args[0] = "5"; // 哲学家数
 78         args[1] = "0"; // 思考时间
 79         args[2] = "deadlock"; // 指定发生死锁
 80 
 81         Philosopher[] philosopher = new Philosopher[Integer.parseInt(args[0])];
 82         Philosopher.ponder = Integer.parseInt(args[1]);
 83 
 84         // first指向left指向的地址,left重新指向其他地方,first不跟随改变
 85         Chopstick left = new Chopstick(), right = new Chopstick(), first = left;
 86         int i = 0;
 87         while (i < philosopher.length - 1) {
 88             philosopher[i++] = new Philosopher(left, right);
 89             left = right;
 90             right = new Chopstick();
 91         }
 92 
 93         if (args[2].equals("deadlock"))
 94             philosopher[i] = new Philosopher(left, first);
 95         else
 96             // 交换最后一个哲学家拿筷子的顺序,打破死锁
 97             philosopher[i] = new Philosopher(first, left);
 98 
 99     }
100 } // /:~

 

 

转载于:https://www.cnblogs.com/yakun/p/3468436.html

你可能感兴趣的:(多线程系列之哲学家进餐)