2014-11-23 3 views
0

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

class ChopStick{ 
    private int count; 
    private boolean inuse; 
    Lock lock = new ReentrantLock(); 
    Condition notInUse = lock.newCondition(); 

    public ChopStick(){ 
     inuse = false; 
    } 

    public void pickUp(){ 
     lock.lock(); 
     try{ 
      while(inuse){ 
       try{ 
        notInUse.await(); 
       }catch(InterruptedException e){} 
      } 
      inuse = true; 
     }finally{lock.unlock();} 
    } 

    public void putDown(){ 
     lock.lock(); 
     try{ 
      inuse = false; 
      notInUse.signal(); 
     }finally{lock.unlock();} 
    } 
} 

class Philosopher extends Thread{ 
    Semaphore sem; 
    private ChopStick ch1,ch2; //chopsticks 
    private int phil; //philosopher id 

    public Philosopher(int p, ChopStick left, ChopStick right, Semaphore s){ 
     phil = p; 
     ch1 = left; 
     ch2 = right; 
     sem = s; 
    } 

    public void run() { 
     while(true){ 
      try { 
       sem.acquire(); 
      } catch (InterruptedException e) {} 
       think(phil); 
       //pickup chopsticks 
       ch1.pickUp(); 
       ch2.pickUp(); 
       eat(phil); 
       //putdown chopsticks 
       ch1.putDown(); 
       ch2.putDown(); 
       sem.release(); 
      } 
     } 

Я имею в виду, когда философ поднимает палочку, используя sem.acquire(), а затем, когда они закончили использовать sem.release(), но я не уверен, если это правильно. Это?

Редактировать Так я реализовал это. Кажется, работает, но я не уверен.

class ChopStick{ 
    private Semaphore sem; 
    public ChopStick(Semaphore s){ 
      sem = s; 
    } 

    public void pickUp(){ 
      try{ 
        sem.acquire(); 
      }catch(InterruptedException e){} 
    } 
    public void putDown(){ 
      sem.release(); 
    } 
+0

https://www.youtube.com/watch?v=M3CNoX8wetM – Anonymous

+0

Я знаю, как это работает, я ищу, чтобы решить с помощью семафоров. – Strobes

+0

@Strobes Новый код может зайти в тупик, см. Редактирование моего ответа, чтобы предотвратить это. –

ответ

4

Вместо того чтобы семафор на Philosopher, я предлагаю положить семафор на Chopstick; звонки Philosopher приобретают семафоры левых и правых палочек для еды и выпускают семафоры палочек для еды, когда это делается. Это заменит ReentrantLock на Chopstick.

Чтобы предотвратить тупик, вы можете использовать tryAcquire(int permits, long timeout, TimeUnit unit), так что Philosopher выпускает семафор левого хохлатого палочки, если ему не удается получить семафоры правого палочки для еды в течение таймаута; если вы используете случайный тайм-аут (например, от 100 до 500 миллисекунд), то каждый Philosopher должен в конечном итоге добиться прогресса.

Edit: Ваш новый Chopstick код рискует тупик - все философы подобрать их левую палочку, а затем ждать навсегда их право палочки, чтобы быть свободным. A tryAcquire позволит философу выпустить свою левую палочку для еды, если после таймаута он не сможет приобрести свою правую палочку для еды, что позволит философу влево продолжать.

class ChopStick{ 
    private static Random random = new Random(); 

    // initialize with one permit 
    private Semaphore sem = new Semaphore(1); 

    public boolean pickUp(){ 
    try { 
     // wait between 100 and 500 milliseconds 
     return sem.tryAcquire(1, random.nextInt(400) + 100, TimeUnit.MILLISECONDS); 
    } catch(InterruptedException e) { 
     return false; 
    } 
    } 

    public void putDown(){ 
    sem.release(); 
    } 
} 

class Philosopher extends Thread { 
    public void run() { 
    while(true){ 
     think(phil); 
     doEat(); 
    } 

    private void doEat() { 
    if(ch1.pickup()) { 
     if(ch2.pickup()) { 
     eat(phil); 
     ch1.release(); 
     ch2.release(); 
     else { 
     ch1.release(); 
     doEat(); 
     } 
    else { 
     doEat(); 
    } 
    } 
} 
+0

I попробуем это и опубликуем результаты, когда смогу. – Strobes

+0

См. Выше edit. – Strobes

+1

Это правильно. «Семафор» должен применяться к общему ресурсу. «Chopstick» - это то, что разделяют, а не «Философ». Помните, проблема состоит в том, что два объекта 'Philosopher' пытаются получить доступ к одному и тому же ресурсу; 'Chopstick'. Если вы оставите это каждому «Философу», чтобы решить, когда все в порядке, чтобы получить «Chopstick», каждый из них, скорее всего, будет жадным и лишенным доступа к нему (каждый «Философ» хочет продолжать есть). Если вы позволяете ресурсу диктовать, когда это нормально, то проблема решена. – hfontanez