Blatt3 - Picasso

Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.

Blatt3 - Picasso
Hi zusammen,
ist es normal, dass bei der Picasso-Aufgabe teilweise Rechtecke frei bleiben?
Ich hab inzwischen alles ge-synchronized (also auch die Methoden), aber auch so bleiben irgendwas zwischen keinem und 7 Feldern ungefärbt.
Woran könnte denn das noch liegen? Ich seh keinen Fehler mehr, der sich im Counter oder da irgendwo verstecken könnte…

Oder ist das Absicht, und soll uns die Hilflosigkeit bei Wettlaufsituationen verdeutlichen? :wink:
Der Code meiner run()-Methode ist folgender:

		while(!leinwand.fertig()){
			int x = (int)(Math.random()*leinwand.getX());
			int y = (int)(Math.random()*leinwand.getY());
			if(!leinwand.istGefaerbt(x, y)){
				leinwand.faerbe(x, y, farbe);
			}
		}

Und manchmal kommt dann (hier mit 50 50 4 als Parametern) so was bei rum:
http://rupran.de/files/pics/uni/picasso.jpg


Wenn zwei Threads die gleichen Koordinaten (x, y) “würfeln”, gleichzetig istGefaerbt(x, y) aufrufen, dann beide false als Ergebnis erhalten (gehen wir davon aus, das entsprechende Feld ist noch nicht gefärbt) färben beide Threads das gleiche Feld und erniedrigen dabei jeweils die Zähler-Variable in der Leinwand. Dementsprechend gibt fertig() dann auch true zurück, obwohl es noch ungefärbte Felder gibt.


Jo, so was dachte ich mir schon… danke trotzdem :slight_smile:


Du kannst den Fehler übrigens durch korrekte Synchronisation vermeiden…


chuckle


Das hieße doch, ich müsste speziell eben istGefaerbt() synchronisieren, oder?
Im Endeffekt sind aber doch alle von den Methoden schon mit synchronized gekennzeichnet…
Irgendwie komm ich net drauf, wie die Threads immer noch gleichzeitig zugreifen können… das einzige, was nicht “synchronized” ist, ist der Konstruktor von Leinwand.
Oder versteh ich das Prinzip vollkommen falsch :wink:


soweit ichs verstanden hab, ist zwar der zugriff auf feld synchronisiert, nicht aber die methode.
Folgendes kann passieren:
Thread 1: istGefarbt(9,2): Lock, Nachschau’n, Unlock
Thread 2: istGefarbt(9,2): Lock, Nachschau’n, Unlock
Thread 1: faerbe(9,2,x): Lock, Färben, Unlock
Thread 2: faerbe(9,2,x): Lock, Färben, Unlock

Wenn du nun allerdings die eine neue methoden faerbeWennLeer machst, welche synchronisiert arbeitet, ist zwar das paralelle arbeiten fürn a…, aber es arbeitet vollständig :wink:


Jo stimmt, hab das nun so ausprobiert, und da färbt’s vollständig… an was man bei Parallelität alles denken muss… :wink:

Wenn ich die neue Methode aber in der Leinwand-Klasse mache, dann ist es ja bei der Abgabe nicht möglich, das zu testen, weil wir ja nur Picasso.java abgeben sollen.
Edit: Aha, ich kann ja auch in Picasso neue Methoden schreiben, und die synchronizen… nice :smiley:


Eine neue Methode ist dafür nicht unbedingt notwendig, du kannst auch einen neuen synchronized-Block benutzen, z.B. so:

synchronized (leinwand) { if(!leinwand.istGefaerbt(x, y)){ leinwand.faerbe(x, y, farbe); } }

Ein solches Problem hast du übrigens immer, wenn du eine Bedingung überprüfst und dann eine Aktion basierend auf dem Ergebnis der Überprüfung der Bedingung ausführst. In den Folien von Prof. Philippsen heißt das “Prüfe-und-Handle-Wettlaufsituation”.


Ich wusste nicht, dass das auch innerhalb der run()-Methode des Threads selber möglich ist, deswegen war ich leicht verwirrt :wink: