2013-06-23 3 views
3

Вот моя реализация проблемы согласия усов Философа. Я работаю только для двух потоков, а остальное страдает от голода, буквально;) Я ценю, если бы вы могли найти причину этого.Головоломка, встречающаяся в столовой Философы код

Вот результат:

Philosopher 2 is eating 
Philosopher 0 is eating 
Philosopher 2 is eating 
Philosopher 0 is eating 
Philosopher 2 is eating 
Philosopher 0 is eating 
Philosopher 2 is eating 
Philosopher 0 is eating 
Philosopher 2 is eating 
Philosopher 2 is eating 
Philosopher 0 is eating 
Philosopher 2 is eating 
Philosopher 0 is eating 

Вот код:

public class PhilosophersDinner { 

    public static void main(String[] args) { 
     Chopstick2[] chopsticks = new Chopstick2[5]; 
     Philosopher [] philosophers = new Philosopher[5]; 

     for (int i = 0; i < 5; i++) { 
      Chopstick2 stick = new Chopstick2(); 
      chopsticks[i] = stick; 
     } 

     for (int i = 0; i < 5; i++) { 
      Philosopher philo = new Philosopher(chopsticks[i] , chopsticks[(i+1)%5], i+""); 
      philosophers[i] = philo; 
     } 

     for (int i = 0; i < philosophers.length; i++) { 
      new Thread(philosophers[i]).start(); 
     } 
    } 

} 

class Philosopher implements Runnable { 

    private final Chopstick2 left; 
    private final Chopstick2 right; 
    private final String id; 

    public Philosopher(Chopstick2 l, Chopstick2 r, String id){ 
     this.left = l; 
     this.right = r; 
     this.id = id; 
    } 

    public void eat(){ 
     if (left.pickUp()) { 
      if (right.pickUp()) { 
       chew(); 
       putDown(); 
      } else left.putDown(); 
     } 
    } 


    public void run(){ 
     for (int i = 0; i < 10; i++) { 
      eat(); 
     } 
    } 

    public void chew(){ 
     try { 
      System.out.println("Philosopher "+id+" is eating"); 
      Thread.sleep(400); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
      // release lock here? 
     } 
    } 

    public void putDown(){ 
     left.putDown(); 
     right.putDown(); 
    } 

} 

class Chopstick2 { 
    private volatile boolean taken = false; 

    public synchronized boolean pickUp(){ 
     if (!taken) { 
      taken = true; 
      return true; 
     } 
     else return false; 
    } 

    public synchronized void putDown(){ 
     taken = false; 
    } 
} 
+1

Я только кратко просмотрел код, но классическое решение этой проблемы состоит в том, чтобы иметь хотя бы одного правого философа и, по крайней мере, одну левую руку, это позволит избежать тупиковой ситуации. Чтобы избежать голодания классически, вы бы использовали монитор (семафор в сочетании с очередью). –

+0

Спасибо, что указал на Джейка, но как он может зайти в тупик, если левая палочка будет выпущена при выборе правильного? – ksiomelo

ответ

1

Проблема заключается в том, что первые два Philosophers получить палочки потратить половину второго еды и в течение этого времени, остальные три посетители обедают, пока не сдадутся и не уйдут.

Одним из решений было бы, чтобы все философы питались в течение определенного количества времени вместо того, чтобы делать определенное количество попыток съесть.

for (long i = System.currentTimeMillis()+10000; i > System.currentTimeMillis();) { 
     eat(); 
    } 
+0

Должно быть '>'. Еще лучше замените это на достойное имя переменной и цикл while. – erickson

+0

спасибо Тиму, что решила проблему! – ksiomelo