2009-03-03 5 views
5

Próbuję nauczyć się podstawowego jistu semafora w problemie Jadącego Filozofa. Teraz, mam tablicę klasy Chopstick, a każdy Chopstick ma semafora z 1 wolny zezwolenia:Problemy semaforowe w Javie z Filozofami Jadalnictwa

public class Chopstick 
{ 
    Thread holder = null; 
    private Semaphore lock = new Semaphore(1); 

    public synchronized void take() throws InterruptedException 
    { 
     this.lock.acquire(); 
     holder = Thread.currentThread(); 

    } 

    public synchronized void release() 
    { 
     this.lock.release(); 
     holder = null; 
    } 
} 

Zmienna uchwyt służy do funkcji, że nie jestem pewien, czy potrzebne są:

public synchronized void conditionalRelease() 
{ 
    if (holder == Thread.currentThread()) 
    { 
     holder = null; 
     this.lock.release(); 
    } 
} 

Program kompiluje się i działa, ale wydaje się, że ma pewne problemy z wypuszczaniem pałeczek. Czasami pałeczki zostają uwolnione, czasami nie. Kiedy nie wypuszczają, program ostatecznie zawiesza się, gdy wszystkie pałeczki są brane i jeden filozof jest głodny.

Oto kod wewnątrz klasy filozof zwolnić chopstick po losowym czasie:

System.out.println(this.name + " is eating"); 
Thread.sleep(this.getRandTime()); 
System.out.println(this.name + " has finished eating"); 

rightChopstick.release(); 
System.out.println(this.name + " has released the right chopstick"); 
leftChopstick.release(); 
System.out.println(this.name + " has released the left chopstick"); 

Mój program ma wyjścia „Filozof 0 skończył jeść”, na przykład, i kontynuuje wykonywanie. Pozostałe dwie linie nigdy się nie wyprowadzają, więc oczywiście coś jest nie tak z tym, co wypuszczam.

Każda pomoc jest doceniana.

Odpowiedz

8

Wpisałbym słowo kluczowe "zsynchronizowane" z twoich podpisów metod. Używasz zewnętrznego mechanizmu blokującego (w tym przypadku semafora). Słowo kluczowe "zsynchronizowane" próbuje uzyskać blokady za pomocą własnego muteksu obiektu. Blokujesz teraz 2 zasoby, które, jak podejrzewam, mogą powodować zakleszczenie.

+0

Ha! Dokładnie to było ... Musiałem wdrożyć te dwa różne sposoby przypisania i skopiowałem kod do pierwszej metody i zapomniałem usunąć zsynchronizowane słowo kluczowe. Miłe znalezisko. –

1

Problem polega na tym, że gdy thread1 ma specyficzny chopstick i kolejnych prób, aby uzyskać ten sam jeden będzie czekać w take() -method on line this.lock.acquire(); ale będzie NIE zwolnić monitor samego obiektu.

Jeśli teraz wątek1 spróbuje zwolnić pałeczkę, nie może wprowadzić metody release() -metod, ponieważ jest nadal zablokowany przez inny wątek oczekujący w take(). To zakleszczenie

1

Wydaje się trochę dziwne, że jesteś zarówno blokowania na pałeczki i mający pomieścić semafora o rozmiarze 1. Ogólnie semafor zapewnia bilety do zasobu, a jeśli masz tylko jeden bilet, to skutecznie wzajemnego wykluczania który jest identyczny z blokadą (blok synchronizowany lub obiekt blokady). Możesz rozważyć fakt, że sam Chopstick jest obiektem blokady.

Zrobiłem wpis na blogu w restauracji filozofów w Javie jakiś czas temu, jeśli jesteś zainteresowany, chociaż tak naprawdę chodzi o to, jak uniknąć impasu, używając innych strategii.

+0

Wygląda na to, że był to element zadania domowego, w którym miał pewne wymagania kulinarne, mówiąc, że musiał używać semaforów. –

+0

Inną rzeczą, którą możesz zrobić, to fakt, że Chopstick rozszerza Semaphore (lub Lock). :) Chociaż to nic nie kupi, jeśli nie wykorzystasz go bezpośrednio. –

0

filozof musi nabyć blokadę po obu chosticks przed jedzeniem początek i będzie pickup leftone pierwszy następnie czekać na prawo więc zacząć jeść więc rozpocząć metody powinny być zsynchronizowane. następujących metod uczyni to działa:

public synchronized void startEating() { 
    leftChopstick.acquire(); 
    rightChopstick.acquire(); 
} 

public void finishEating(int id) { 
    leftChopstick.release(); 
    rightChopstick.release(); 
} 
1

Upewnij się, że nie ma żadnego blokowania lub zsynchronizowane kluczowe używany. Poniższy kod dla pałeczki działa dobrze dla mnie ..Nie pro, ale musi dać jakiś pomysł;

public class Chopstick { 
private boolean inuse; 
Semaphore sem; 

public Chopstick(){ 

    inuse = false; 
    sem = new Semaphore(1); 
} 
public void pickUp() 
{ 
    try 
    { 
     while(inuse) 
     { 
      try 
      { 
       sem.acquire(); 

      } 
      catch(InterruptedException e) {} 
     } 
     inuse = true; 
    }catch(Exception e){} 
} 
public void putDown() 
{ 
    try 
    { 
     inuse = false; 
     sem.release(); 

    } 
    catch (Exception e){} 
} 

}