Alte Klausuraufgabe Threads

DaSt

Bekanntes Mitglied
Hallo,

in der letzten Klausur war folgende Aufgabe zu Threads dran:

"Programmieren Sie eine Klasse mit dem Namen Counter, die sich als Thread starten lässt. Wird ein solcher Thread gestartet, gibt er in der Command-Line die Zahlen von 1 bis 500.000 aus. Wenn mehrere Threads dieser Klasse gleichzeitig laufen, darf keine Zahl mehrfach ausgegeben werden. Es darf aber auch keine Zahl ausgelassen werden. Sichern Sie diese Eigenschaft in Ihrem Quellcode ab. Bemerkung: Sie müssen die Threads nicht starten."

Die Lösung war folgende:

Java:
public class Counter extends Thread {

   private static final int MAX = 500000;
   private static int currentCount = 0;


  @Override
  public void run() {
     while ( incrementIfValid() );
  }

    private synchronized boolean incrementIfValid() {
    
       if ( currentCount < MAX ) {
            System.out.println(++currentCount);
            return true;
            }
       return false;
      }
}

Wieso ist denn hier sichergestellt, dass keine Zahl ausgelassen bzw. doppelt vorkommen kann?

Danke
 
Zuletzt bearbeitet von einem Moderator:

DaSt

Bekanntes Mitglied
ok, synchronized haben wir noch nicht besprochen. Im Netz habe ich folgende def. gefunden:
"Um Klassen threadsicher zu machen, kann man Methoden der Klassen als synchronized deklarieren. Die Qualifizierung mit synchronized bewirkt, dass zuerst eine begonnene synchronized Methode zu Ende ausgeführt wird, bevor eine neue synchronized Methode in einem anderen Thread begonnen werden kann. Das heißt, synchronized Methoden können nicht konkurrierend zueinander ablaufen, sondern werden immer sequentiell nacheinander ausgeführt. In dieser Ausgabe unserer Kolumne werden wir uns die Details von synchronized genauer ansehen."

Aber dann sind es doch eig. nur zwei Methoden die nacheinander aufgerufen werden oder?
 

nvidia

Bekanntes Mitglied

Ich stelle die Hypothese auf, die Lösung ist falsch. Der Grund, das synchronized, wie im Code dargestellt, wirkt auf eine Instanzmethode, d.h. auf ein lebendes Objekt und in dem Falle dient das Objekt selbst als Lock. D.h. werden 3 Counter erstellt new Counter().start, new Counter.start() usw. wird auf das jeweilige voneinander unterschiedliche Counter-Objekt synchronisiert. Der zu verändernde Wert ist jedoch eine statische Klassenvariable und deshalb müsste auf die Klasse synchronisiert werden, das geht aber wiederrum nur wenn der Methode incrementIfValid noch ein static vorangestellt wird. Das es so scheint als ob es funktioniert ist Zufall.

Das wird auch richtig deutlich wenn man n-Threads wirklich gleichzeitig startet und das Erhöhen des Zählers aus dem IO rauszieht. Wäre es ordentlich synchronisiert dürfte nichts passieren. Bei dem folgenden Testprogramm wird bei mir jedoch regelmäßig 3x die 3 ausgegeben (man muss sich natürlich alle Zahlen sortieren, in Excel z.B.) und die 1er fehlen ganz. Die CyclicBarrier ist dafür um zu warten bis alle Threads soweit sind.

Um die Lösung zu korrigieren müsste die Methodendefinition wie folgt aussehen private static synchronized boolean incrementIfValid()

Java:
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
* Beispiel für fehlerhafte Synchronisation
*/

class Counter extends Thread {

    private static final int MAX = 500000;
    private static int currentCount = 0;

    @Override
    public void run() {
        try {
            Test.gate.await();
        } catch(InterruptedException e) {
            e.printStackTrace();
        } catch(BrokenBarrierException e) {
            e.printStackTrace();
        }

        while(incrementIfValid())
            ;
    }

    private synchronized boolean incrementIfValid() {

        if(currentCount < MAX) {
            ++currentCount;
            System.out.println(currentCount);
            return true;
        }
        return false;
    }
}

public class Test {

    public static final CyclicBarrier gate = new CyclicBarrier(3);

    public static void main(String... args) {
        new Counter().start();
        new Counter().start();
        new Counter().start();
    }
}
 
Zuletzt bearbeitet:
K

kneitzel

Gast
Also die Funktion incrementIfValid wird ja in einer While Schleife immer wieder aufgerufen. Wenn nun mehrere Threads laufen, dann soll das synchronized dazu führen, dass die Ausführung in allen Threads immer so lange wartet, bis die Ausführung in einem anderen Thread beendet ist.

Im übertragenen Sinne ist das also sozusagen das Schloss an der Klotür. Synchronized ist ein Schloss an der Klotür. Es kann immer nur ein Thread rein. Durch das synchronized wird sicher gestellt, dass beim Eintritt direkt die Tür geschlossen ist und andere müssen draussen warten.

Der Einwand von nvidia ist nun, dass diese Klotür ja Instanzgebunden ist, d.h. wenn ich drei Instanzen von der Klasse erstelle, dann habe ich auch drei Klotüren. Und das führt dann zu Problemen, denn nun können mehrere Threads gleichzeitig aufs Klo und genau das galt es ja zu verhindern.

Und das kann man ja einfach einmal testen. Zum Test einfach einmal eine kleine main Routine geschrieben:

Java:
public static void main(String[] args) {
    int numberOfCounter = 5;

    Counter[] counter = new Counter[numberOfCounter];

    // Create counter
    for (int i = 0; i<numberOfCounter; i++)
        counter[i] = new Counter();

    // Start counter
    for (int i=0; i<numberOfCounter; i++)
        counter[i].start();

    // wait for counter to finish
    for (int i=0; i<numberOfCounter; i++) {
        try {
            if (counter[i].isAlive()) counter[i].wait();
        } catch (InterruptedException ex) {
            // Nothing to do!
        }
    }
}

Und dann im Test erhalten:
Code:
499977
499885
499979
499980
499981
499982
499983
499984
499985
499986
499987
499988
499989
499990
499991
499992
499993
499994
499995
499996
499997
499998
499999
500000
499868
499866

==> Lösung ist schlicht falsch.

Die Funktion incrementIfValid static gemacht und schon sieht die Ausgabe besser aus :)[/code]
 
Zuletzt bearbeitet von einem Moderator:

thecain

Top Contributor
Ist natürlich korrekt, da war ich wohl ein bisschen schnell im lesen...

Zur Ergänzung, möglich wäre auch:

Java:
private boolean incrementIfValid() {
    synchronized (Counter.class) {
        if (currentCount < MAX) {
            System.out.println(++currentCount);
            return true;
        }
        return false;
    }
}

oder

Java:
private static final Object kloTuerSchloss = new Object();
private boolean incrementIfValid() {
    synchronized (kloTuerSchloss) {
        if (currentCount < MAX) {
            System.out.println(++currentCount);
            return true;
        }
        return false;
    }
}
Um nochmal auf die Klotüren zu kommen ;)
 
K

kneitzel

Gast
Wobei mir die Lösung mit der statischen Variable kloTuerSchloss mit Abstand am Besten gefällt :)
 

DaSt

Bekanntes Mitglied
nachdem wir synchronized jetzt in der Vorlesung besprochen haben, habe noch eine Frage: Warum brauche ich extra eine boolean incrementIfValid() Funktion , die ja eig. nichts anderes macht als bis nach MAX zu erhöhen.

Also warum geht z.B. folgendes nicht:

Java:
private final static Object o = new Object

private static void zaehlen(){
  synchronized(o){
         for(int i = 0; i<MAX; i++){
          System.out.println("Nr. "+i);
         }
}

Danke
 
Zuletzt bearbeitet von einem Moderator:

Tobse

Top Contributor
Der Code, den du da gepostet hast, funktioniert so auch nicht. Damit Zählt der erste Thread, der startet, auf MAX und die anderen machen garnix. Wenn dann:

Java:
static int counter = 0;
public void run() {
    while(counter < MAX) {
        synchronized(o) {
            if (counter < MAX)
                System.out.println(i++);
        }
    }
}

P.S.: Was der Code hier macht nennt sich double-lock. Zu Threading bringe ich auch immer gerne dieses Bild:
b591eeab7c20e197b7601e0cd4253181.jpg


Multithreading ist ein komplexes Thema und es gibt viel Literatur, die sich nur damit beschäftigt. Das in 1-2 Vorlesungen abzufrühstucken geht nicht.
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
C Alte Klausuraufgabe - UML in Java implementieren Java Basics - Anfänger-Themen 1
F Hat es noch einen Sinn, alte Versionen zu lernen Java Basics - Anfänger-Themen 45
Proxy Stack erweitern mit neuem Array falls der alte voll ist!? Java Basics - Anfänger-Themen 5
P Neue Java v8 JRE Version nicht über alte drüber installierbar: Wie sonst? Java Basics - Anfänger-Themen 7
J Kopierte Datei soll alte ersetzen. Java Basics - Anfänger-Themen 6
G Konsole gibt "alte" sachen aus Java Basics - Anfänger-Themen 3
T Alte Einträge im Array werden von neuen überschrieben Java Basics - Anfänger-Themen 5
Fab1 alte Java Datei wird ausgeführt (trotz Änderung) Java Basics - Anfänger-Themen 4
K Iteration - Alte und neue For Schleife Java Basics - Anfänger-Themen 17
M Problem mit getter, liefert nur alte Werte Java Basics - Anfänger-Themen 6
S JDK installieren alte Versionen deinstallieren Java Basics - Anfänger-Themen 2
R Neue GUI öffnen und die Alte schließen Java Basics - Anfänger-Themen 6
N Das alte Thema "File Encoding" Java Basics - Anfänger-Themen 2
S alte dateien löschen Java Basics - Anfänger-Themen 9
G Initialisierung + alte Werte Java Basics - Anfänger-Themen 7
Z DB-Abfrage liefert alte Werte Java Basics - Anfänger-Themen 11
G neue for Schleife in alte for Schleife umwandeln. Java Basics - Anfänger-Themen 2
S paintComponent, neue Instanz überschreibt wohl alte Instanz Java Basics - Anfänger-Themen 6
B Programmanalyse (Klausuraufgabe) Java Basics - Anfänger-Themen 8
F Referenzvariable vom Typ "Integer" definieren. (Klausuraufgabe) Java Basics - Anfänger-Themen 5
D Übung zur Klausuraufgabe Java Basics - Anfänger-Themen 18
D Klausuraufgabe in Java Java Basics - Anfänger-Themen 6
pindakaas fehler in Klausuraufgabe? Java Basics - Anfänger-Themen 15
T Klausuraufgabe Bordcomputer Java Basics - Anfänger-Themen 9
N Klausuraufgabe hilfe Java Basics - Anfänger-Themen 6
J Verständnis Problem mit return --> Klausuraufgabe Java Basics - Anfänger-Themen 4
G Klausuraufgabe Aufruflogik Java Basics - Anfänger-Themen 3
H Nutzt Eclipse alle CPU-Threads beim Ausführen von Java-Programmen? Java Basics - Anfänger-Themen 4
C Threads und Swing Java Basics - Anfänger-Themen 9
berserkerdq2 Wo finde ich in der Java Api die Notation zu Threads bezüglich Synchronized? Java Basics - Anfänger-Themen 14
berserkerdq2 Findet eine parallele Verarbeitung in Java bei Threads erst statt, wenn man die Methoden auch synchronized? Und wie sieht bei Conditions aus? Java Basics - Anfänger-Themen 8
B Monitor als Schranke von Threads Java Basics - Anfänger-Themen 20
W Threads Alphabet Java Basics - Anfänger-Themen 20
H Threads Anfänger Java Basics - Anfänger-Themen 17
1 Threads parallel laufen Java Basics - Anfänger-Themen 11
B Threads Problem mit mehreren Threads Java Basics - Anfänger-Themen 38
M Threads Java Basics - Anfänger-Themen 12
L Threads Synchronisierung zwischen threads Java Basics - Anfänger-Themen 4
M Threads Java Basics - Anfänger-Themen 2
A Threads Java Basics - Anfänger-Themen 9
A Threads Java Basics - Anfänger-Themen 13
A Threads und .join Java Basics - Anfänger-Themen 14
W Threads starten Java Basics - Anfänger-Themen 2
X Threads Zwei Threads, aber doppelte Ausgabe verhindern (synchronized) Java Basics - Anfänger-Themen 54
J Wieviele threads? Java Basics - Anfänger-Themen 9
J Problem bei seriellem Start von Threads Java Basics - Anfänger-Themen 11
O Threads Java Basics - Anfänger-Themen 2
L Buchungssystem und Threads Java Basics - Anfänger-Themen 2
O Threads - Synchronize(), join(), wait(), notify(), yield() Java Basics - Anfänger-Themen 6
L Klassen NFC Reader und JavaFx Problem -> threads? Java Basics - Anfänger-Themen 2
A Kommunikation zwischen nebenläufigen Threads Java Basics - Anfänger-Themen 4
S Gemeinsame Ressource und Mehrfachinstanziierung von Threads Java Basics - Anfänger-Themen 16
S Verklemmung Threads Java Basics - Anfänger-Themen 11
B Threads 2 Threads gleichzeitig laufen lassen Java Basics - Anfänger-Themen 1
M Threads Threads laufen sequenziell, statt gleichzeitig. Java Basics - Anfänger-Themen 9
M Threads run Methode Java Basics - Anfänger-Themen 4
javajoshi mehrere Threads: Methoden zentral unterbringen Java Basics - Anfänger-Themen 8
javajoshi Problem mit zwei Threads und Arrays (Runnable) Java Basics - Anfänger-Themen 12
L Threads Mit Threads JLabel ändern! Java Basics - Anfänger-Themen 2
K Matrixen berechnen nach Worker Master Paradigma mit Threads Java Basics - Anfänger-Themen 4
S Kleine Frage zu Threads Java Basics - Anfänger-Themen 3
M Mit 2 Threads eine Zahl hochzählen Java Basics - Anfänger-Themen 13
T Threads Synchronisieren Java Basics - Anfänger-Themen 6
D Frage Threads Java Basics - Anfänger-Themen 6
Z Threads Executor Framework - Aufgabe auf n Threads aufteilen Java Basics - Anfänger-Themen 10
Z Threads Threads - Zugriff auf Ressourcen ohne(Lock, Synchronized) Java Basics - Anfänger-Themen 2
kilopack15 Verständnisfrage zur Verwendung von notify() bei Threads Java Basics - Anfänger-Themen 2
kilopack15 Mehrere Threads in einer Klasse Java Basics - Anfänger-Themen 8
H Threads funktionieren nicht Java Basics - Anfänger-Themen 4
J Aufgabe(Threads) richtig verstanden/implementiert Java Basics - Anfänger-Themen 27
R Threads aufeinander warten lassen? Java Basics - Anfänger-Themen 10
T Threads Durch threads gestartete Prozesse killen Java Basics - Anfänger-Themen 2
J Threads Java Basics - Anfänger-Themen 38
A Threads Threads bestimmte Aufgaben zuweisen... Java Basics - Anfänger-Themen 3
R Threads in JavaFX Java Basics - Anfänger-Themen 3
E Threads Doppelte Threads beenden Java Basics - Anfänger-Themen 4
F Sicheres Zurückmelden aus Threads Java Basics - Anfänger-Themen 0
G Threads zum Thema Threads??? null Ahnung Java Basics - Anfänger-Themen 4
Q Threads Threads in Swing Anwendungen Java Basics - Anfänger-Themen 5
J ConcurrentCalculation Multi Threads in Java Java Basics - Anfänger-Themen 3
P Threads Trotz Threads wird nur 1 Prozessorkern ausgelastet Java Basics - Anfänger-Themen 7
M "restartable" threads Java Basics - Anfänger-Themen 11
M Threads - summieren Java Basics - Anfänger-Themen 13
W Klassen Variable einer anderen Klasse ändern (Threads) Java Basics - Anfänger-Themen 3
E Threads - Programm analysieren Java Basics - Anfänger-Themen 2
E join() bei zwei Threads Java Basics - Anfänger-Themen 2
T Threads Threads richtig synchronisieren Java Basics - Anfänger-Themen 3
D [Concurrency/Threads] Code Umsetzung Schriftlich Java Basics - Anfänger-Themen 2
D Threads Java Basics - Anfänger-Themen 4
M Threads nio Dateien kopieren, Threads und Gui Java Basics - Anfänger-Themen 0
N Verweise auf Variablen in verschiedenen Threads Java Basics - Anfänger-Themen 4
T Java-Threads Java Basics - Anfänger-Themen 0
G Moving Objects with Threads (implements Runnable) Java Basics - Anfänger-Themen 1
F Threads funktionieren auf JPanel nicht Java Basics - Anfänger-Themen 1
M Problem mit Threads Java Basics - Anfänger-Themen 11
M Threads - wo gehören sie hin? Java Basics - Anfänger-Themen 3
S 2D-Spiel mit Threads... Java Basics - Anfänger-Themen 3
J Threads Java Basics - Anfänger-Themen 3
F ExecutorService und offene Threads Java Basics - Anfänger-Themen 3
P Threads Threads nicht nebenläufig Java Basics - Anfänger-Themen 7

Ähnliche Java Themen

Neue Themen


Oben