Re: einfaches Problem beim Synchronisieren



hi all,

also.. das Programm war doch:

public class MainSynchronisieren4 {
public static void main(String[] args){
ThreadCounter tc1 = new ThreadCounter();
ThreadCounter tc2 = new ThreadCounter();

Thread t1 = new Thread (tc1);
Thread t2 = new Thread (tc2);
t1.start();
t2.start();
}
}

class ThreadCounter implements Runnable{
public static int zahl=0;
public Object MyLockObjekt = new Object();

public void run(){
while(zahl<1000)
synchronized(MyLockObjekt){
System.out.println(zahl++);
}
}
}

man beachte das tahl static ist and das MyLockObject *nicht static* ist, und auch *keine Klasse*. Es hilft übrigens sehr viel bei solchen Programmen Fehler zu finden wenn man sich an die Konventionen für Gross/Kleinschreibung von Sun hält. In dem Fall heisst das das MyLockObject eigentlich myLockObject heissen sollte. Der Name selbst spielt zwar keine wirkliche Rolle, aber wie viele Instanzen es von diesem Objekt gibt spielt eine Rolle. In deinem Beispiel hat jeder Thread eine eigene Instanz, dh, dein synchronized(MyLockObjekt) juckt den anderen Thread überhaupt nicht und eigentlich hast du den unsynchronisierten Fall hier.

Jetzt machst du ein System.out.println(zahl++); während für den in prinzipiell garantiert (ich meine das Memmorymodell definiert das so ab java5, bin aber nicht sicher, Ralf bitte korrigiere mich!) ist, dass er gelesen wird, aber das heisst nicht dass das Rückschreiben auch mit dem korrektem Wert passieren wird. zahl++ ist ja im prinzip: lade Feld zahl, erhöhe den Wert um eins, schreibe Feld zahl. Also 3 Operatiomen und stellen wir uns mal folgendes vor:


zahl = 10

Thread 1 Thread 2
lade Feld zahl in x (x=10) -
erhöhe Wert (x=11,zahl=10) lade Feld zahl in y (y=10)
schreibe Feld zahl (zahl=11) -
- erhöhe wert (y=11,zahl=11)
lade Feld zahl in x (x=11) schreibe Feld zahl (zahl=11)
gebe x aus => 11 lade Feld zahl in y (y=11)
- gebe y aus => 11


die Ausgabe wäre dann: 11, 11 und nicht 10, 11. Ganz einfach weil 10++ zweimal ausgeführt wurde, weil der eine Thread nicht schnell genug den Wert zurückschreiben konnte. Theoretisch geht das mit dem Zurückschreiben noch viel verrückter, aber das lassen wir mal... Jedenfalls muss in diesem Fall die Ausgabe nicht monoton steigend sein, allerdings kann sie es sein. führt man diese Operationen allerdings oft genug aus, so sit die Wahrscheinlichkeit doch recht hoch, dass man solch einen Fehler in der Abfolge beobachten wird. Richtig müsste das Programm sein, wenn:

public class MainSynchronisieren4 {
public static void main(String[] args){
ThreadCounter tc1 = new ThreadCounter();
ThreadCounter tc2 = new ThreadCounter();

Thread t1 = new Thread (tc1);
Thread t2 = new Thread (tc2);
t1.start();
t2.start();
}
}

class ThreadCounter implements Runnable{
public static int zahl=0;
public static Object MyLockObjekt = new Object();

public void run(){
while(zahl<1000)
synchronized(MyLockObjekt){
System.out.println(zahl++);
}
}
}

in dem Fall synchronisieren sich die Threads auch tatsächlich und die Operation samt Ausgabe erfolgt erst bei einem Thread und dann vielleicht beim nächsten Thread... aber auf jeden Fall in der korrekten Reihenfolge.

Gruss theo

--
Jochen "blackdrag" Theodorou
The Groovy Project Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/
http://www.g2one.com/
.



Relevant Pages

  • Re: einfaches Problem beim Synchronisieren
    ... Da ich zwei Threadcounter Objekte habe, hat Attribut zahl von Thread ... Wenn man zwei Threadcounter Objekte hat und man das Attribut zahl bzw. ... myLockObjekt hat und man auf _ein und dieselbe_ zahl zugreifen will, ...
    (de.comp.lang.java)
  • Re: einfaches Problem beim Synchronisieren
    ... Da ich zwei Threadcounter Objekte habe, hat Attribut zahl von Thread ... Wenn man zwei Threadcounter Objekte hat und man das Attribut zahl bzw. ... myLockObjekt hat und man auf _ein und dieselbe_ zahl zugreifen will, ...
    (de.comp.lang.java)
  • Re: einfaches Problem beim Synchronisieren
    ... ausgegeben. ... Thread A: 1 ... Garantiert wird halt nur dass der Thread läuft, aber nicht in welcher exakten Reihenfolge die Threads jeweils an die Reihe kommen. ... > class ThreadCounter implements Runnable{ ...
    (de.comp.lang.java)