Threads und synchronized

Jens81

Gesperrter Benutzer
Hallo,

ich versuche mich gerade an Threads und Synchronisation mit einigen kleinen Testprogrammen.

Angenommen ich habe zwei Threads, A und B. A und B greifen unter anderem auf die Statische Funktion "DateToSqlDate" aus einer Klasse FormatUmwandlung zu.

Java:
public synchronized static java.sql.Date DateToSqlDate(Date in) {
		java.sql.Date out = new java.sql.Date(in.getTime());

		return out;
	}

Wird hier synchronized benötigt?

Bei lesenden Methoden brauche ich ja eigentlich keine sync wenn ich das richtig verstanden habe. Bei den Schreibenden bin ich mir nicht sicher, wann ich das Schlüsselwort benötige... (z.B. erst bei Zugriffen auf ein gemeinsames Objekt, z.B. eine Liste etc.?)
 
Zuletzt bearbeitet:
wenn zwei threads auf die gleichen daten zugreifen sollte man grundsätzlich synchronisieren, auch bei den lesenden methoden, bzw wenn die gelesenen werte parallel modifiziert werden können. damit der eine thread nicht etwas liest, und bevor der wert verarbeitet ist, der andere thread diesen wert verändert.

natürlich ist es zwecklos wenn zwei threads nicht die gleichen methoden verwenden 🙂

in deinem beispiel wird synchronized gebraucht, weil beide threads ihr eigenes date mitbringen und (wenn sie an der falschen stelle unterbrochen werden) das out des nachfolgers wieder mit rausnehmen. korrigiert mich, wenn ich was falsches sage. 🙂
 
wenn zwei threads auf die gleichen daten zugreifen sollte man grundsätzlich synchronisieren, auch bei den lesenden methoden, bzw wenn die gelesenen werte parallel modifiziert werden können. damit der eine thread nicht etwas liest, und bevor der wert verarbeitet ist, der andere thread diesen wert verändert.
jain ... wenn thread 1 nur liest um den aktuellen Fortschritt anzuzeigen ist das Banane ... wenn Thread 1 ,ot Werten arbeiten muss die Thread 2 erstellt, dann ja

in deinem beispiel wird synchronized gebraucht, weil beide threads ihr eigenes date mitbringen und (wenn sie an der falschen stelle unterbrochen werden) das out des nachfolgers wieder mit rausnehmen. korrigiert mich, wenn ich was falsches sage. 🙂
nein ... "Date in" existiert in dem Moment schon - für jeden Thread ... und das neue Date wird jedesmal auf dem Heap neu erzeugt - für jeden Thread ... btw: lokalen Variablen landen jedesmal auf den Stack des jeweiligen Threads

hand, mogel
 
@Atze
voll falsch gesehen 😉

die Methode ist nichts anderes als z.B.
double Math.sin(double)
und die will ja auch niemand synchronisieren bzw. kann auch niemand ändern

synchronisieren nur wenn auf gleiche Daten zugegriffen wird, hier etwa statische Variablen, was nicht passiert,
strenggenommen wäre denkbar, dass zwei Threads dasselbe Date-Objekt übergeben,
aber das ist dann erstens nicht das Problem dieser Methode, denn dann kann es ja überall Probleme mit dem Date-Objekt geben
und zweitens wird hier auch nur die Zeit ausgelesen, was selbst bei überlappenden Zugriff kein Problem machen sollte
 
...wird synchronized gebraucht, weil beide threads ihr eigenes date mitbringen und (wenn sie an der falschen stelle unterbrochen werden) das out des nachfolgers wieder mit rausnehmen

Kann das noch jemand bestätigen? 🙂 Das würde ja bedeuten das auch alle Getter, die mehr als einen möglichen Rückgabewert besitzen, synchronisiert werden müssten (Bisher ist zumindest nichts schief gegangen).
z.B. bei
Java:
public Date getLastModifiedDate(Typ typ) {
		switch (typ) {
			case TRAIN: return this.datumTrain;
			case VALID: return this.datumValid;
			case KLASS: return this.datumKlass;
			default: return null;
		}
	}


Edit: Ok, hat sich dann erledigt 🙂
Vielen Dank euch allen!
 
Zuletzt bearbeitet:
ok, dann hab ich wohl mist erzählt 🙂 sorry

ich hab jetzt so gedacht:

A kommt mit 10 uhr, out wird erzeugt, A wird unterbrochen
B kommt, erzeugt out mit 12 uhr, geht raus
A kann weitermachen, nimmt auch das 12 uhr out mit

war dann wohl n denkfehler, schande über mich 🙂
 
Zuletzt bearbeitet:
denkbar wärs, zum Glück besteht diese Art Problem nicht, Code ist inmateriell,
die lokalen Variablen, auf die zugegriffen wird, hat jede Ausführung in ihrem lokalen Stack,
sonst ginge auch Rekursion nicht, ineinandergeschachteltes Ausführen derselben Methode
 
@Atze
die Methode ist nichts anderes als z.B.
double Math.sin(double)
Kein gutes Beispiel. Die Methoden sind doch recht unterschiedlich ;-)

@Atze
strenggenommen wäre denkbar, dass zwei Threads dasselbe Date-Objekt übergeben,
aber das ist dann erstens nicht das Problem dieser Methode, denn dann kann es ja überall Probleme mit dem Date-Objekt geben
und zweitens wird hier auch nur die Zeit ausgelesen, was selbst bei überlappenden Zugriff kein Problem machen sollte
Nicht ganz. Dass java.util.Date leider nicht immutable ist unschön. Dadurch ist aber auch der lesende Zugriff getTime nicht threadsafe, denn der Wert ist ein long und das Attribut ist nicht volatile deklariert. Somit sollte in diesem Fall die Methode synchronisiert werden oder expliztit als nicht threadsafe gekennzeichnet sein. Wäre das Attribut immutable, wäre eine Synchronisation unnötig.
 
statische Methoden, die nur Parameter bearbeiten/ verwenden, gibt es in er API sicher tausende und ich habe noch keine einzige synchronisierte gesehen,
glaube FArts Ausführungen, zu welchem Zweck auch immer,
oder halte dich an die einfache Regel wie sie überall gilt: Synchronisation wenn auf Klassenattribute oder statische Attribute zugriffen wird
 
also kann out nicht von beiden threads verändert werden, da jeder thread seinen eigenen stack hat und dort jeweils eins liegt, soweit richtig?
hört sich schlüssig an!
*edit2*
dachte bisher nur objekte landen grundsätzlich im heap, und nur primitives und methodenaufrufe auf dem stack. vielleicht ist das bei threads anders, und ich glaub das jetzt erstmal, bis ich nachgeschaut hab 🙂
-----
die rückgabe von in.getTime() kann von beiden threads bspw zur hälfte geschrieben sein, da das long nicht volatile ist. auch richtig?
hört sich auch gut an, aber was ich dann nicht versteh ist, beide threads können in dem beispielfall doch völlig interschiedliche Date objekte mitbringen. also wäre die einzige möglichkeit der vermischung, wenn das out erzeugt wird, also der wert als long an den sql.Date konstruktor übergeben wird. (dass halt der letzendliche long wert aus zwei aufrufen zusammengesetzt würde)
die beiden Date objekte an sich, also deren longs, werden doch im besten falle nur von einem thread mitgebracht? wann kann der andere da reinpfuschen?
oder denk ich ganz falsch?
gibts noch meinungen dazu?

*edit*
slater ist beim posten dazwischengerutscht 🙂 also würd mich dann doch an slaters meinung halten, obwohl fart ja "auf meiner seite" ist! :/ aber slaters meinung ist (für mich) technisch besser nachzuvollziehen. vielleicht kann nochjemand was dazu sagen
 
Zuletzt bearbeitet:
FArt bezog sich glaube ich den Punkt
> strenggenommen wäre denkbar, dass zwei Threads dasselbe Date-Objekt übergeben

aber das hatte ich eigentlich nur zur Ergänzung erwähnt, danach kann man doch nicht gehen,
niemand würde Collections.sort(list) synchronized machen, nur weil der Anwender theoretisch zwei Threads starten kann, die dieselbe Liste zum Sortieren übergeben und da dann alles durcheinander geht

das muss die einzelne Methode nicht verhindern, außer man arbeitet explizit für solche Fälle

edit:
ok bei Date ist es etwas eher denkbar als bei List, weil man Dates üblicherweise gerne überall verteilt statt Kopien zu erstellen, Date wird wie ein unveränderlicher String oder ein primitiver Datentyp verwendet, ist es aber nicht,
naja, ganz extrem gedacht
 
Zuletzt bearbeitet von einem Moderator:
*edit2*
dachte bisher nur objekte landen grundsätzlich im heap, und nur primitives und methodenaufrufe auf dem stack. vielleicht ist das bei threads anders, und ich glaub das jetzt erstmal, bis ich nachgeschaut hab 🙂

ich hab nachgeschaut 🙂 und meine, habs richtig verstanden:
2 threads -> 2 jvm stacks mit jeweils 2 nicht (native method) frames -> 2 out referenzen auf 2 objekte in einem gemeinsamen heap!

hab ich irgendwas missverstanden?

VM Spec The Structure of the Java Virtual Machine

ab 3.5 wurds interessant 🙂
 
hm, das Thema nochmal, also du warst bei

> A kommt mit 10 uhr, out wird erzeugt, A wird unterbrochen
> B kommt, erzeugt out mit 12 uhr, geht raus

A und B kommen mit unterschiedlichen Dates auf dem Heap,
dass einer dieser Speicherplätze im Heap mit dem anderen überschrieben wird ist ja wenig realistisch,

> A kann weitermachen, nimmt auch das 12 uhr out mit

wenn dann könne man denken (so dachte ich in meinen Erklärungen zu deinen Gedenke 😉 ),
dass für die fortgeführte Ausführung von A nun eine Referenz auf das zweite Objekt im Heap (von B) verwendet wird,

und diese Referenzen, die lokalen Variablen, die liegen auf dem Stack, daher ist dieser Fehler ausgeschlossen,
der Inhalt der Variablen, oft kb-große Objekte, liegt auf dem Heap, richtig,

ein Objekt kann ja von verschiedenen Variablen/ Referenzen aus angesprochen werden
 
enn dann könne man denken (so dachte ich in meinen Erklärungen zu deinen Gedenke 😉 ),
dass für die fortgeführte Ausführung von A nun eine Referenz auf das zweite Objekt im Heap (von B) verwendet wird,

ja, so ungefähr, ich hatte angenommen, das beide die gleiche referenz und somit das gleiche objekt verändern. hab nicht über 2 die eigenen frames, und somit über 2 objekte nachgedacht, wenn beide threads die gleiche methode (mein gedanke -> gleicher frame)
betreten. :/ danke 🙂 vielleicht sollte ich mal öfter in die specs schauen 😀
 

Zurück
Oben