Frage

Ich versuche, den Grund jist einen Semaphore im Speise Tutor Problem zu lernen. Gerade jetzt, ich habe eine Reihe von Klasse Ess-Stäbchen, und jeder Chopstick hat eine Semaphore mit 1 verfügbar Erlaubnis:

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;
    }
}

Der Halter Variable wird für eine Funktion verwendet, die ich bin nicht sicher, ich brauche:

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

Das Programm kompiliert und ausgeführt, scheint aber einige Probleme zu haben, die Stäbchen freigibt. Manchmal bekommen die Stäbchen freigegeben, manchmal tun sie nicht. Wenn sie nicht loslassen, was schließlich das Programm auflegt, wenn alle der Stäbchen genommen und ein Philosoph ist hungrig.

Hier ist der Code innerhalb der Tutor-Klasse der Ess-Stäbchen nach unbestimmter Zeit freizugeben:

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");

Mein Programm funktioniert Ausgang „Philosoph 0 hat Essen fertig“, zum Beispiel, und setzt die Ausführung. Die beiden anderen Linien nie ausgegeben, so offensichtlich etwas falsch mit der Art, wie ich die Freigabe bin.

Jede Hilfe ist willkommen.

War es hilfreich?

Lösung

Ich würde den ‚synchronisiert‘ Keyword aus Ihren Methodensignaturen. Sie sind mit einem externen Verriegelungsmechanismus (die Semaphore, in diesem Fall). Der ‚synchronisiert‘ Keyword versucht, Sperren zu bekommen eigenes Mutex Objekt verwenden. Sie sind nun auf 2 Ressourcen Sperren, die ich vermuten, dass ein Deadlock könnte verursachen.

Andere Tipps

Das Problem ist, dass, wenn thread1 ein spezifisches Ess-Stäbchen und eine anderes versucht, das gleiche zu bekommen es in der take()-Methode auf der Leitung this.lock.acquire(); warten, aber es wird nicht lösen Sie den Monitor auf dem Objekt selbst .

Wenn jetzt thread1 die Ess-Stäbchen zu lösen versucht, es nicht die release()-Methode geben kann, da sie nach wie vor von dem anderen Thread wartet in take() gesperrt sind. Das ist eine Sackgasse

Es scheint ein wenig verwirrend, dass Sie beide auf der Ess-Stäbchen sind Sperren und nachdem er eine Semaphore der Größe 1. halten Im Allgemeinen wird eine Semaphore bietet Tickets für eine Ressource, und wenn Sie nur ein Ticket haben, das ist effektiv mutual exclusion, die identisch ist eine Sperre (entweder ein synchronisierten Block oder ein Verriegelungsobjekt). Sie könnte in der Tat machen die Chopstick das Sperrobjekt selbst betrachten.

Ich habe eine Blog-Post auf den speisenden Philosophen in Java eine Weile zurück, wenn Sie daran interessiert sind, obwohl es wirklich ist, wie Deadlock zu vermeiden, indem sie andere Strategien.

Stellen Sie sicher, dass es keine ist Blockieren oder synchronisiert Schlüsselwort verwendet. Der folgende Code für den Chop-Stick funktioniert gut für mich .. kein Profi, sondern muss geben u eine Vorstellung;

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){}
}

}

muss Philospher Sperre erhält auf beiden chosticks vor dem Start Essen und Pickup leftone zuerst, dann warten, rechts, so starten, so startet Methode essen soll synchronisiert werden. Folgende Methoden werden es funktioniert:

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

public void finishEating(int id) {
    leftChopstick.release();
    rightChopstick.release();
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top