3

У меня проблема с кодом Java, который должен имитировать проблему столовых фоллосов, которая описана здесь: http://en.wikipedia.org/wiki/Dining_philosophers_problem Я хочу выводить текущее состояние всех философов каждый раз, когда один из них ест или думает. Результат должен выглядеть примерно так: «O X O o X (2)», где «X» означает, что философ ест, «O» означает, что он думает, а «o» означает, что он ждет палочек для еды. Число в скобках указывает номер философа, состояние которого изменилось. Проблема в том, что есть только философы 1 и 3 (иногда 2 и 4), в то время как другие всегда думают или ждут развилки, и это повторяется постоянно, поэтому результат выглядит следующим образом:Яблочные мониторы-фанаты-философы

OXOOO (2)

O X O ХО (4)

O O O X O (2)

O O O O O (4)

O X O O O (2)

o X o X o (4)

O O O X O (2)

...

Полный код здесь:

import java.util.concurrent.locks.Condition; 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; 

class Stick{ 
    boolean available; 
    public Stick(){ 
     available = true; 
    } 
    public void setAvailability(boolean flag){ 
     this.available = flag; 
    } 
    public boolean getAvailability(){ 
     return available; 
    } 
} 

class Philosopher extends Thread{ 
    private int id; 
    private Stick l, r; 
    private Lock monitor; 
    private Condition[] cond; 
    private Problem p; 

    private void outputState(int _id){ 
     StringBuffer sb = new StringBuffer(); 
     for(int i=0; i<5; i++) 
      sb.append(p.getState(i) + " "); 
     System.out.println(sb + "(" + (_id+1) + ")"); 
    } 

    private void takeChopSticks(int _id) throws InterruptedException{ 
     monitor.lock(); 
     try{ 
      p.setState(_id, "o"); 
      while(!l.getAvailability() || !r.getAvailability()){ 
       cond[_id].await(); 
      } 
      l.setAvailability(false); 
      r.setAvailability(false); 
      p.setState(_id, "X"); 
      outputState(_id); 
     }finally{ 
      monitor.unlock(); 
     } 
    } 

    private void eat() throws InterruptedException{ 
     Thread.sleep(1000); 
    } 

    private void think(int _id) throws InterruptedException{ 
     Thread.sleep(2000); 
    } 

    public void run(){ 
     while(true){    
      try{ 
       takeChopSticks(this.id); 
       eat(); 
       releaseChopSticks(this.id); 
       think(this.id); 
      }catch(InterruptedException e){System.out.println("srusila se metoda run()");} 

     } 
    } 

    private void releaseChopSticks(int _id) throws InterruptedException{ 
     monitor.lock(); 
     try{ 
      l.setAvailability(true); 
      r.setAvailability(true); 
      cond[_id].signalAll(); 
      cond[(_id+4)%5].signalAll(); 
      p.setState(_id, "O"); 
      outputState(_id); 
     }finally{ 
      monitor.unlock(); 
     } 
    } 

    public Philosopher(Problem _p, int _id, Stick _l, Stick _r, Lock m){ 
     cond = new Condition[5]; 
     monitor = m; 
     id = _id; 
     l = _l; 
     r = _r; 
     p = _p; 
     for(int i=0; i<5; i++) 
      cond[i] = monitor.newCondition(); 
    } 
} 

public class Problem { 
    Thread[] t; 
    Stick[] s; 
    private enum State {O, X, o}; 
    private State[] state; 

    public State getState(int id){ 
     return state[id]; 
    } 

    public void setState(int id, String s){ 
     if(s == "o") 
      state[id] = State.o; 
     else if(s=="O") 
      state[id] = State.O; 
     else if(s=="X") 
      state[id] = State.X; 
    } 

    public Problem(){ 
     state = new State[5]; 
     t = new Thread[5]; 
     s = new Stick[5]; 
     for(int i=0; i<5; i++){ 
      s[i] = new Stick(); 
      state[i] = State.O; 
     } 
     Lock m = new ReentrantLock(); 
     for(int i=0; i<5; i++) 
      t[i] = new Philosopher(this, i, s[i], s[(i+4)%5], m); 
     for(int i=0; i<5; i++) 
      t[i].start(); 

    } 

    public static void main(String[] args){ 
     new Problem(); 
    } 
} 

Я знаю, что есть Allready несколько вопросов о обедающих философов в Java , но ни один из них, похоже, не помогает, и мой код немного отличается. Благодарю.

+0

ваш класс 'Stick' кажется, необходимо' volatile' ключевое слово на 'available' переменной – hoaz

+0

спасибо, но это не работает :( – dmacan23

ответ

0

Я немного изменил его и, наконец, работает. Код:

import java.util.concurrent.locks.Condition; 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; 

class Chopstick{ 
    private boolean availability; 

    public Chopstick(){ 
     availability = true; 
    } 

    public boolean getAvailability(){ 
     return availability; 
    } 

    public void setAvailability(boolean flag){ 
     availability = flag; 
    } 
} 

class Helper{ 
    private Lock mutex = null; 
    private Condition[] cond; 
    private String[] state; 
    private int[] id; 

    private void outputState(int id){ 
     StringBuffer line = new StringBuffer(); 
     for(int i=0; i<5; i++) 
      line.append(state[i] + " "); 
     System.out.println(line + "(" + (id+1) + ")"); 
    } 

    public Helper(){ 
     id = new int[5]; 
     mutex = new ReentrantLock(); 
     state = new String[5]; 
     cond = new Condition[5]; 
     for(int i=0; i<5; i++){ 
      id[i] = i; 
      state[i] = "O"; 
      cond[i] = mutex.newCondition(); 
     } 
    } 

    public void setState(int id, String s){ 
     state[id] = s; 
    } 

    public void grabChopsticks(int id, Chopstick l, Chopstick r){ 
     mutex.lock(); 
     try{ 
      setState(id, "o"); 
      while(!l.getAvailability() || !r.getAvailability()) 
       cond[id].await(); 

      l.setAvailability(false); 
      r.setAvailability(false); 
      setState(id, "X"); 
      outputState(id); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     }finally{ 
      mutex.unlock(); 
     } 
    } 


    public void releaseChopsticks(int id, Chopstick l, Chopstick r){ 
     mutex.lock(); 
     try{ 
      setState(id, "O"); 
      l.setAvailability(true); 
      r.setAvailability(true); 
      cond[(id+1)%5].signalAll(); 
      cond[(id+4)%5].signalAll(); 
      outputState(id); 
     }finally{ 
      mutex.unlock(); 
     } 
    } 
} 


class Philosopher implements Runnable{ 
    private Helper hlp; 
    private Chopstick l, r; 
    private int id; 
    public Philosopher(int id, Chopstick l, Chopstick r, Helper i){ 
     this.hlp = i; 
     this.l = l; 
     this.r = r; 
     this.id = id; 
    } 

    private void eat(){ 
     try{ 
      Thread.sleep(2000); 
     }catch(InterruptedException e){} 
    } 

    private void think(){ 
     try{ 
      Thread.sleep(2000); 
     }catch(InterruptedException e){} 
    } 

    public void run(){ 
     while(true){ 
      hlp.grabChopsticks(id, l, r); 
      eat(); 
      hlp.releaseChopsticks(id, l, r); 
      think(); 
     } 
    } 
} 

public class Problem { 
    private Chopstick[] s; 
    private Philosopher[] f; 
    private Helper hlp; 

    private void init(){ 
     s = new Chopstick[5]; 
     f = new Philosopher[5]; 
     hlp = new Helper(); 
     for(int i=0; i<5; i++) 
      s[i] = new Chopstick(); 

     for(int i=0; i<5; i++){ 
      f[i] = new Philosopher(i, s[i], s[(i+4)%5], hlp); 
      new Thread(f[i]).start(); 
     } 

    } 

    public Problem(){ 
     init(); 
    } 

    public static void main(String[] args){ 
     new Problem(); 
    } 
} 
+0

Из-за' mutex' это выглядит только 1 философ может начать захватывать в любой момент? –

Смежные вопросы