Semaphor

Lybrial

Bekanntes Mitglied
Hallo,

ich wollte nun mal Semaphore einsetzen für eine Parkhaus-Simulation.
Das Parkhaus hat, durch das Sempaphor vorgegeben, 10 Stellplätze.
20 Autos versuchen nun in diesem Parkhaus zu parken:

Parken => sem.acquire()
Los fahren => sem.release()

Jetzt lasse ich in erine Schleife die Autos einfahren, eine kurze Zeit
warten (sleep()) und dann wieder losfahren. Wenn das Parkhaus voll
ist, sollen die anderen Autos natürlich so lange warten.

Jetzt habe ich die Situation, dass mein Parkhaus öffnet, 10 Fahrzeuge
parken und es dann wieder schließt. Es fahren keine Autos wieder ab
und vor allem konnten nicht alle 20 Autos parken.
Das Programm terminiert auch nicht:

Java:
import java.util.Random;

class Car extends Thread {
	private static final Random rand = new Random();
	private Parkhouse parkhouse;
	
	public Car(Parkhouse aParkhouse) {
		parkhouse = aParkhouse;
	}
	
	public void run() {
        	
		while(true) {
			parkhouse.enter();
	        busy();      
	        parkhouse.exit();
		}
  
    }
	
    private void busy() {
        try {
          sleep(rand.nextInt(500));
        } 
         catch (InterruptedException e) {}
    }
}

Java:
import java.util.concurrent.Semaphore;

class Parkhouse {
	private Semaphore sem = new Semaphore(9);
	
	public void openParkhouse() {
		
		System.out.println("Das Parkhaus öffnet!");
		
	}
	
	synchronized public void enter() {
		
		System.out.println("Auto parkt!");
		
		try {
			sem.acquire();
	    } catch (InterruptedException e) {}
		

	}
	
	synchronized public void exit() {
		
		System.out.println("Auto fährt!");
		sem.release();
	
	}
	
	public void closeParkhouse() {
		
		System.out.println("Das Parkhaus schließt!");
		
	}
}

Java:
public class Main {
	public static void main(String[] args){
		
		Parkhouse parkhouse = new Parkhouse();
		Car[] auto = new Car[20];
		Thread[] thread = new Thread[20];
		
		parkhouse.openParkhouse();
		
		for (int i = 0; i < auto.length; i++) {
			auto[i] = new Car(parkhouse);
		}
		
		for (int i = 0; i < auto.length; i++) {
			thread[i] = new Thread(auto[i]);
			thread[i].start();
		}
		
		parkhouse.closeParkhouse();

	}
}
 
S

SlaterB

Gast
das synchronized muss aus den Methoden weg, Semaphor schafft das alleine,
im Moment hält das erste wartene Auto den synchronized-Lock während es am Semaphor wartet,
keines der parkenden Autos kann zum exit(), weil wegen synchronized blockiert

solange die Auto-Threads laufen endet das Programm natürlich nicht,
die interessieren sich übrigens bisher auch nicht dafür, ob Parkhaus geschlossen ist

achte noch auf deine System.out.println()-Meldungen, "Auto parkt!" sollte erst NACH dem Semaphor stehen,
erst dann ist das Auto wirklich drin,
gib noch jedem Auto/ Thread einen Namen/ eine Nummer oder gibt einfach Thread.currentThread() mit aus bei deinen Ausgaben, um die einzelnen Autos zu unterscheiden

für den Anfang arbeite lieber mit nur 2-3 Autos und 2 Plätzen oder so, dann wirds übersichtlicher
 

Lybrial

Bekanntes Mitglied
Das closeParkhouse sollte auch nur symbolisieren, dass nun alle Autos einmal geparkt waren.
Durch die Änderungen habe ich jetzt eine Endlosschleife.
Wenn ich das Programm starte parken zunächst 10 Autos, dann kommt die Ausgabe das das
Parkhaus geschlossen wurde und dann fährt und parkt abwechselnd ein Auto aber unendlich
lang obwohl ich nur 20 Autos initialisiert habe.
 
S

SlaterB

Gast
> Das closeParkhouse sollte auch nur symbolisieren, dass nun alle Autos einmal geparkt waren.

Vorsicht mit Nebenläufigkeit, die close-Methode kann auch ausgeführt werden, bevor sich die anderen Threads überhaupt bemühen anzufangen

----

die 20 Autos fahen für sich jeweils in einer Schleife ständig rein und raus, wieso sollte es nicht eine Endlosschleife an Ausgaben geben?
> obwohl ich nur 20 Autos initialisiert habe
schon ein Auto würde genügen wenn es nie aufhört

> und dann fährt und parkt abwechselnd ein Auto aber unendlich
hast du mit Ausgaben bestätigt dass es immer dasselbe ist?
 

Lybrial

Bekanntes Mitglied
Okay, danke, funktioniert soweit.
Nur eine Sache noch....wie kann ich das Parkhaus genau dann schließen lassen,
wenn alle Autos wieder gefahren sind?
 
S

SlaterB

Gast
solange ein ständiges Kommen und Gehen ist und das Parkhaus nie leer ist, geht ja offensichtlich nix,
da kann ich dir einen ebenso offensichtlichen fachlichen Tipp geben: sorge dafür dass keiner mehr rein kann, aber warte ab bis dann alle raus sind und schließe dann ab..

also setze einen boolean X der bei enter() berücksichtig wird, wobei allerdings dafür zu sorgen ist dass die Auto-Thread nicht durchdrehen wenn sie nicht reinkommen,
und das Prüfen auf Leer könnte entweder exakt eine bestimmte Zeit später stattfinden lassen, oder auch in der exit-Methode:
wenn X gesetzt ist und gerade das letzte Auto abfährt, dann irgendwas tun,
wobei es da vielleicht Nebenläufigkeitsprobleme geben kann, dass mehrere gleichzeitige Methodenabläufe denken es wäre Ende
 

chalkbag

Bekanntes Mitglied
wenn ich noch etwas einwerfen darf, momentan werden die ersten 10 Autos bevorzugt.

Das glaube ich aufgrund folgenden Source-Codes.

Java:
while(true) {
            parkhouse.enter();
            busy();      
            parkhouse.exit();
        }

Typischerweise würde der Thread nicht schnell genug verdrängt werden und so würde direkt aufeinander gefolgt pharhouse.exit, while(true) und parhouse.enter() ausgeführt werden.

Gerechtigkeit (für die Töftöfs!) gäbe es z.B. wenn du nach dem parkhouse.exit() ein Thread.Yield machen würdest. Ich bin ehrlich ich hab es nicht getested, aber gib doch den TöfTöfs mal einen Namen und lass immer beim parken den Autonamen ausgeben. Auch wäre durch die aktuelle Logik der Main-methode das "Anstellen in der Schlange" nicht realisiert. Da wäre eine Queue vielleicht praktisch.

Aber vielleicht spinn ich auch nur etwas rum.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
N Semaphor Programm Java Basics - Anfänger-Themen 4

Ähnliche Java Themen


Oben