synchronized

Hallo Leute,

kann mir einer der werten Jave-Versteher .-) erklären, weshalb folgender Code nicht synchronisiert?
Hier soll durch 2 Threads die Variable x durch die Schleife auf den Wert 4.000 gezählt werden.
Die Werte sind allerdings bei jedem Durchgang immer noch unterschiedlich trotz Synchronisation.o_Oo_O

Java:
public class SynchedThreads2 implements Runnable {
    
    static Object lock= new Object(); 
        
        int x; 
        
        @Override
        public void run() { 
            int i; 
            for (i=0; i<2000; i++) { 
                synchronized(lock) { 
                    x++; 
                }
                
            }
            System.out.println(Thread.currentThread().getName() 
                    + " has finished after " + i + " loops");
            
        }

        public static void main(String[] args) {
            
            CreazyThreads2 c = new CreazyThreads2(); 
            new Thread(c).start();
            new Thread(c).start();
            
            try {
                Thread.sleep(500);
            }catch (InterruptedException e) { 
                e.printStackTrace();
            }
            synchronized(lock) {
            System.out.println("x is: " +c.x);
        }
    }

}
 
Statt mit Thread.sleep() eine beliebige Zeit zu warten, kannst du auch einfach Thread.join() verwenden:
Java:
public class SynchedThreads2 implements Runnable {
  static Object lock = new Object();
  int x;
  @Override
  public void run() {
    int i;
    for (i = 0; i < 2000; i++) {
      synchronized (lock) {
        x++;
      }
    }
    System.out.println(Thread.currentThread().getName() + " has finished after " + i + " loops");
  }
  public static void main(String[] args) throws InterruptedException {
    SynchedThreads2 c = new SynchedThreads2();
    Thread t1 = new Thread(c);
    t1.start();
    Thread t2 = new Thread(c);
    t2.start();
    t1.join(); // <- Auf den ersten Thread warten
    t2.join(); // <- Auf den zweiten Thread warten
    synchronized (lock) {
      System.out.println("x is: " + c.x);
    }
  }
}
 
Wenn ich das hier:
richtig verstehe, dann synchronisierst du den Zugriff auf dein Object lock. Du willst aber den Zugriff auf dein int synchronisieren.

Womit ich sehr gute Erfahrungen gemacht habe ist außerdem das hier:
 
Ah, der Titel für ein neues Spiel: Crazy Threads 2 :)

Ich würde aber dann schon auch SynchedThreads2 instantiieren und nicht CreazyThreads2:
Java:
        public static void main(String[] args) {

            SynchedThreads2 c = new SynchedThreads2();
...
oh man. Ich nehme alles zurück und behaupte das Gegenteil. Das kommt davon wenn man älteren Code kopiert und bei den Anpassungen etwas vergisst.

Mission Problem: gelöst :))))

thx alot .-)
 
Damit hält er alle Threads an.
Hö? Durch synchronized Threads anhalten? Sobald man in der main aus dem synchronized-Block rausgeht kommen die Threads ja wieder an die Reihe (sofern sie nicht eh schon terminiert sind).

Die Threads sind ja längst terminiert zu dem Zeitpunkt, nach dem wait. Jedenfalls auf meiner Kiste.
Angenommen sie wären nicht terminiert, dann würde der Main-Thread durch den Monitor Zugriff bekommen, x ausgeben und die Threads würden im Hintergrund ihre Arbeit fertig machen. Also das gleiche wie ohne den synchronized-Block.
 
Ich sollte den Code vielleicht wirklich mal genauer lesen und nicht nur überfliegen bevor ich in die Tastatur haue. :(
Ich schätze mal er wollte den Zugriff von seinem System.out-Aufruf auf sein x mit den Threads synchronisieren. In diesem Fall kann man wohl wirklich darauf verzichten.

Ja, wenn die Threads schnell genug durch sind und die Wartezeit ausreicht, sind sie wohl terminiert. Bis du nachgeschaut hast sind sie auf jeden Fall terminiert, denn die laufen ja auch weiter wenn du die main z.B. mit dem Debugger anhältst.
 
Bei mir hängt das bekanntermaßen davon ab, wie schnell ich kurble :)
Da mir selbst bewusst war, dass es verschiedene Kisten gibt habe ich die beide Fälle durchdacht, die man durch anpassen der Wartezeit provozieren kann:
A) Threads bereits terminiert
B) Threads noch nicht terminiert
und komme zu dem Ergebnis, dass es ohne und mit synchronized Block das gleiche ergibt. Und somit kam die Frage auf, wofür der Block dann dort ist.
Meine Gedankengänge waren
A) ich habe synchonized nicht ganz durchdrungen
B) ich übersehe etwas
C) jemand hat den Block dort benutzt in der fälschlichen Annahme, dass dort auf die Terminierung der Threads gewartet wird.
C.1) das würde jedoch auch wieder in Widerspruch zum vorherigen Warten mit Thread.sleep stehen. Wäre dann ja doppelt gemoppelt...
D) höäähh?
 
und komme zu dem Ergebnis, dass es ohne und mit synchronized Block das gleiche ergibt.
Wenn wir davon ausgehen, dass die Threads noch laufen, gibt es schon einen Unterschied, denn x++ ist nicht atomar, die Zuweisung an ein int dagegen schon. Letztlich ist das aber graue Theorie, denn den Unterschied wird man nicht merken :)
 
Bei mir hängt das bekanntermaßen davon ab, wie schnell ich kurble :)
Die Sache ist einfach die, dass sleep() keine Zusicherung gibt, dass danach alle Threads schon "fertig" sind. (Das synchronized auch nicht.)

Durch das reservieren starten und wechseln der Threads ist es nicht ganz unrealistisch, dass 500ms nicht ausreichend seien können...
 
Die Sache ist einfach die, dass sleep() keine Zusicherung gibt, dass danach alle Threads schon "fertig" sind. (Das synchronized auch nicht.)

Durch das reservieren starten und wechseln der Threads ist es nicht ganz unrealistisch, dass 500ms nicht ausreichend seien können...
Die Überlegung war tatsächlich, wenn die Zeit nicht ausreicht, geht man mit dem zusätzlichen Synch-Block auf Nummer Sicher.
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben