PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [JAVA] Eine Methode aufrufen, während sie noch läuft


Hardwaretoaster
2009-01-21, 19:04:01
Ich habe gerade was beobachtet udn verusche mir das zu erklären:
Ich habe einen Thread, der in Unregelmäßigen Abständen eine Methdoe des selben Objekts aufruft (etwas in eine Liste einfügen und anschließnd von dort aus die Abarbeitung anstoßen)

Nun kann es passieren, dass der Aufruf noch nicht fertig ist, ehe ein ernueter Aufruf stattfindet.
Meine Beobachtung: Dann passiert einfach nichts, aber ein Fehler kommt auch nicht.

Ich habe mein Problem anders gelöst, aber die Hintergünde würden mich dazu interessieren. Leider weiß ich nicht, nach welchem begriff ich da zu suchen habe.

robobimbo
2009-01-21, 19:29:38
kurz aus der hüfte geschossen, ist die implementierung der liste nicht threadsafe?

Das Verhalten ist lt. Deinen Beobachten zwar "immer" gleich - aber undefiniert, kann wo anders (andere vm) unterschiedlich ablaufen.

Ich nehm an Dein Lösung war eine synchronized List zu verwenden?

( http://java.sun.com/j2se/1.4.2/docs/api/java/util/Collections.html#synchronizedList(java.util.List) )

Hardwaretoaster
2009-01-21, 19:48:30
Also ich nutze im prinzip eine Array-List.
In der Grundausführung ist die ja nicht threadsafe.
Meine Lösung war jetzt ganz simpel die Bearbeitenmethode periodisch anzustoßen und zu schauen, ob noch was in der Liste ist anstatt sie beim Einfügen aufzurufen.

Das tut jetzt auch.
Problem mit Threadsicherheit dürfte nur sehr eingeschränkt auftreten, ich missbruache die Liste als eine Art Warteschlage: Angefügt wird immer am Ende, wenn irgednwas drin ist, wird das erste rausgenommen.

Monger
2009-01-21, 19:55:17
Bei Nicht Thread-sicheren Objekten können da schon solche Anomalien auftauchen.
Was du beschreibst, könnte folgende Ursache haben:

- Thread X betritt die Methode
- Thread X fängt an, irgendwelche Daten zu verändern
- Thread Y betritt die Methode
- Thread Y fängt an, irgendwelche Daten zu verändern
- Thread Y wird schneller fertig, und verlässt die Methode
- Thready X wird ebenso fertig, und legt seine Ergebnisse ab

Wenn beide Methoden irgendwie auf dem Index der Liste arbeiten, kann es sein dass Thread Y an genau dem selben Index gearbeitet hat wie Thread X, und somit Thread X als letzter Bearbeiter das Ergebnis von Y überbügelt.

Multithreading bietet lauter solche Anomalien. Und es sind viele Operationen nicht atomar von denen man es gar nicht glaubt, z.B. ein i++ .

Solche Anomalien sind echt tückisch, und höllisch schwer zu analysieren. Das einzige was hilft, ist halt für solche Zwecke sich auf threadsichere Strukturen zu verlassen.

Hardwaretoaster
2009-01-21, 20:14:43
Hm, wenn es keine rein logischen Fehler hat, dann wird es wohl eine solche Anomalie sein, nur warum ich den Fehler nach der Anpassung nicht mehr reproduziert bekomme ist mir nicht klar.
Ich sollte wohl noch 'ne ganze Menge Material zu nebenläufigkeit lesen. War alles auf die Schnelle gezimmert, was ein Glück ist das eine Übung und kein Produktivsystem.

Monger
2009-01-21, 20:24:35
Thread Anomalien sind in aller Regel sporadisch. Das macht sie auch so gefährlich: beim debuggen entdeckt man die fast nie.

Coda
2009-01-22, 00:33:40
Vor allem Race Conditions sind böse. Deadlocks bemerkt man wenigstens auf jeden Fall ;)

Ganon
2009-01-22, 09:58:23
Das tut jetzt auch.
Problem mit Threadsicherheit dürfte nur sehr eingeschränkt auftreten, ich missbruache die Liste als eine Art Warteschlage: Angefügt wird immer am Ende, wenn irgednwas drin ist, wird das erste rausgenommen.

Warum nutzt du dafür nicht eine Queue?

darph
2009-01-22, 09:59:30
Ganz toll ist es, wenn man auf die Implementierung keinen Einfluß hat, weil die Bibliothek von Dritten stammt. (Ganz aktuell: JFreeChart. Alle 300 ms einen Wert in ein Diagramm einfügen, Boom, ConcurrentThreadModificationException)

Monger
2009-01-22, 10:59:04
Von deiner Beschreibung her klingt es so, als könnte vielleicht eine
ConcurrentLinkedQueue (http://java.sun.com/javase/6/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html) das richtige für dich sein.

Ich muss aber zugeben, ich hab mit Nebenläufigkeit zu wenig Erfahrung, um da Tipps zu geben. Ich weiß nur, dass sie regelmäßig Kopfschmerzen auslöst! :ugly:

Tiamat
2009-01-22, 14:39:55
Hier gibt´s mehrere Möglichkeiten.

Also ein Thread ruft eine Methode innerhalb seiner run() auf, die etwas in ein Array ablegt. Und

1.) Das du kümmerst dich selbst um die Synchronisation. Das bedeutet, du setzt vor jeder zugreifenden Methode das Schlüsselwort synchronized. z.b
public synchronized void legWasAb(Object whatever). Dann gibt es nur noch einen Thread, der auf diese Liste zugreift. Die andere muss solange warten, bis der Thread den synchronized Block verlassen hat.
Die warteten Threads kannst du dann mit wait() und notify() oder notifyAll() zum warten oder aufwachen koordinieren.

2.) Du benutzt aus dem Collection Framework synchronisierte Datenstrukturen.
Vector ist z.b ne synchronisierte ArrayListe, Hashtable ist synchronized, ArrayBlockingQueue.
Da musst du dich quasi um gar nix mehr kümmern.

Gruß
Tiamat

Hardwaretoaster
2009-01-22, 17:03:20
Warum nutzt du dafür nicht eine Queue?


Mangelhafte API-Kenntnisse, Asche über mein Haupt :frown:

@Monger und Tiamat
Danke! Werde mich da mal versuchen reinzufuchsen

shink@work
2009-01-23, 08:37:38
Ganz toll ist es, wenn man auf die Implementierung keinen Einfluß hat, weil die Bibliothek von Dritten stammt. (Ganz aktuell: JFreeChart. Alle 300 ms einen Wert in ein Diagramm einfügen, Boom, ConcurrentThreadModificationException)
Auch bei solchen Problemen sind die Concurrent-Klassen als rundum-sorglos-Paket zu gebrauchen. Verwende sie schon seit sie noch gar nicht Teil des JDKs waren und hab nur sehr gute Erfahrungen damit. Klar, so viel tun die auch wieder nicht dass man sie in den Himmel loben müsste aber man kann sie wirklich oft gebrauchen.