Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
ich bin am rumprobieren mit synchronisation gewesen und dabei auf folgendes Problem gestosen:
Java:
public class Speicherproblem {
int counter = 0;
public static void main(String[] args) {
Speicherproblem s = new Speicherproblem();
s.test();
}
public void test(){
new Thread(new Inkrementor()).start();
new Inkrementor().run();
System.out.println(counter);
}
public synchronized void add(){
counter++;
}
public class Inkrementor implements Runnable{
@Override
public void run() {
for(int i = 1; i <= 10000; i++){
add();
}
}
}
}
Ich erstelle hierbei zwei Inkrementoren, die in verschiedenen Threads counter um eins erhöhen.
Auch wenn sie dies in einer synchronized Methode machen, kommt als result ein zufälliger Wert zwischen
10.000 und 20.000 herraus.
Warum, wie macht mans richtig?
hm, hab jetzt hier am lappi kein eclipse zum testen, aber rein vom gefühl her sieht das n bischen merkwürdig aus. hast du dich vorher mal eigehend mit dem thema concurrency / threads beschäftigt? was soll denn überhaupt rauskommen? 20.000?
also was so auffällt beim drüberschauen:
1. zeile 3 - vielleicht volatile setzen
2. zeilen 12 & 13 - warum die verschiedenen aufrufe? und niemals run() aufrufen, nur start(), sonst ist es eine simple methode, kein multithreading
3. die nested class nicht public machen, sonst braucht sie ne eigene datei. kompiliert dass denn so eigentlich? *grübel*
würd grundsätzlich nochmal über den code nachdenken
public void test(){
new Thread(new Inkrementor()).start();
new Inkrementor().run();
System.out.println(counter);
}
Dein Problem entsteht durch diese Methode. Wenn die Zeile mit dem println ausgeführt wird, dann ist der eine Inkrementor fertig, d.h. counter ist mindestens 10000. Der Fortschritt des parallelen Threads ist aber völlig unklar, er kann zwischen 0 (kam noch nicht zum Zug) und 10000 (ist bereits fertig) liegen.
Funktionieren müsste es so (habs nicht getestet)
Java:
public void test(){
Thread t = new Thread(new Inkrementor());
t.start();
new Inkrementor().run();
t.join();
System.out.println(counter);
}
Ich habe jetzt counter volatile gemacht, bringt nichts.
Zu run() vs start().
Schaut nochmal hin, das run() bezieht sich lediglich auf die Klasse Inkrementor, welche von Runnable abgeleitet ist.
Funktionieren tut das so:
Ich starte einen neuen Thread der dann anfängt counter zu erhöhen.
Derweil erhöhe ich im Ursprungsthread counter ebenfalls (new Inkrementor.run()).
Die nested class ist schlecht mit public, sehe ich ein, habe das auch sofort private gemacht.
Auswirkungen auf das Ergebnis hatte dies aber natürlich nicht.