B
blubb2
Gast
servus.
ich hab hier einen quellcode:
Wenn der aufgerufen wird, sind die Zahlen nach kürzester Zeit doppelt, etwas später kommt nur noch eine Zahl in dem Array vor..
Ich erkläre mir das so: Die beiden Threads starten.
Thread1 möchte 4,5 vertauschen. er ruft die Methode vertausche(4,5) auf.
Hier nochmal deren Code:
Dann weist er dem array[4] = array[5] zu.
Zu diesem Zeitpunkt steht in array[4] und array[5] diesselbe Zahl.
Erst im nächsten Schritt setzt er nämlich in array[5] den alten Wert von array[4].
Der zweite Mischer Thread arbeitet dann evt. mit einem Array in dem zwei Zahlen vorkommen, und die Methode ausgabe() gibt direkt schonmal dieses fehlerhafte Array aus.
Wenn man einen der beiden Threads auskommentiert, dann kommen wieder doppelte Zahlen vor, weil die Ausgabe "rumpfuscht". Eine möglichkeit wäre die Ausgabe nicht in einer Endlosschleife aufzurufen, sondern immer dann wenn das vertauschen abgeschlossen ist. Also z.B. in der run-Methode nach vertauschen(i,j). Das geht aber nicht, da von dort nicht auf die "Ausgabe()" Methode zugreifen kann. Außerdem ist das Array garnicht sichtbar im Thread. Eine andere Möglichkeit (wenn man nur einen Thread hat) wäre dann wohl synchronized zu verwenden. Ich würde dann also die Methoden ausgabe() und vertausche() synchronized deklarieren. Das würde angeben dass immer nur ein Thread in das Objekt "hinein" darf.
Der Thread ruft also wieder vertausche auf und vertauscht. Dann verlässt er das Objekt. Erst jetzt darf aus der Endlosschleife heraus wieder die ausgabe()-Methode aufgerufen werden, erst wenn die abgeschlossen ist kann der Thread wieder kommen und wieder vertauschen. Auf den ersten Blick funktioniert es jetzt auch so dass keine doppelten Einträge mehr vorkommen. Aber nur bei einem Thread! Mit dem zweiten Thread müsste es aber genauso funktionieren, oder?
Also beispiel:
Thread 1 kommt an und will vertauschen. Er "nimmt sich" das Lock des Objekts.
Jetzt muss die Main-Methode die gerne ausgabe() aufrufen würde warten und der zweite Thread der auch vertauschen will muss auch warten. Wenn der erste Thread fertig ist gibt er das Lock ab und der nächste darf seine Methode aufrufen. So klingt das sehr logisch und es dürften so theoretisch keine doppelten Zahlen mehr vorkommen.
Scheint ebenfallls auch wieder zu funktionieren.
Stimmt das so vom Prinzip her wie ich das erklärt habe?
Und nochwas: Das Lock bezieht sich ja immer auf das Objekt...also sobald eine sychronized Methode aufgerufen wird, dürfen keine anderen synchronized methoden des Objekt aufgerufen werden, oder? Wenn ich noch eine Methode in dem Objekt hätte, die aber nicht synchronized ist, dann würde die aufgerufen werden können, auch wenn das Lock von einem anderem Thread gehalten wird, oder?
Lg.
L-ectron-X hat diesen Beitrag am 04.02.2008 um 18:16 Uhr editiert.
Code-Tags repariert.
ich hab hier einen quellcode:
Code:
import java.util.Random;
public class Mischen {
private int[] array = {0,1,2,3,4,5,6,7,8,9};
public void vertausche(int i, int j) {
int k = array[i];
array[i] = array[j];
array[j] = k;
}
private void ausgabe(){
System.out.print("[");
for(int i=0; i<9; i++) {
System.out.print(array[i] + ",");
}
System.out.println(array[9] + "]");
}
public static void main(String[] args) {
Mischen m = new Mischen ();
Mischer mischer1 = new Mischer(m);
Mischer mischer2 = new Mischer(m);
mischer1.start();
mischer2.start();
while(true) {
m.ausgabe();
}
}
}
class Mischer extends Thread {
Random random;
Mischen mischen;
public Mischer(Mischen m) {
random = new Random();
mischen = m;
}
public void run() {
while(true) {
int i = random.nextInt(10);
int j = random.nextInt(10);
vertausche(i,j);
}
}
private void vertausche(int i,int j) {
mischen.vertausche(i,j);
}
}
Wenn der aufgerufen wird, sind die Zahlen nach kürzester Zeit doppelt, etwas später kommt nur noch eine Zahl in dem Array vor..
Ich erkläre mir das so: Die beiden Threads starten.
Thread1 möchte 4,5 vertauschen. er ruft die Methode vertausche(4,5) auf.
Hier nochmal deren Code:
Code:
public void vertausche(int i, int j) {
int k = array[i];
array[i] = array[j];
array[j] = k;
}
Dann weist er dem array[4] = array[5] zu.
Zu diesem Zeitpunkt steht in array[4] und array[5] diesselbe Zahl.
Erst im nächsten Schritt setzt er nämlich in array[5] den alten Wert von array[4].
Der zweite Mischer Thread arbeitet dann evt. mit einem Array in dem zwei Zahlen vorkommen, und die Methode ausgabe() gibt direkt schonmal dieses fehlerhafte Array aus.
Wenn man einen der beiden Threads auskommentiert, dann kommen wieder doppelte Zahlen vor, weil die Ausgabe "rumpfuscht". Eine möglichkeit wäre die Ausgabe nicht in einer Endlosschleife aufzurufen, sondern immer dann wenn das vertauschen abgeschlossen ist. Also z.B. in der run-Methode nach vertauschen(i,j). Das geht aber nicht, da von dort nicht auf die "Ausgabe()" Methode zugreifen kann. Außerdem ist das Array garnicht sichtbar im Thread. Eine andere Möglichkeit (wenn man nur einen Thread hat) wäre dann wohl synchronized zu verwenden. Ich würde dann also die Methoden ausgabe() und vertausche() synchronized deklarieren. Das würde angeben dass immer nur ein Thread in das Objekt "hinein" darf.
Der Thread ruft also wieder vertausche auf und vertauscht. Dann verlässt er das Objekt. Erst jetzt darf aus der Endlosschleife heraus wieder die ausgabe()-Methode aufgerufen werden, erst wenn die abgeschlossen ist kann der Thread wieder kommen und wieder vertauschen. Auf den ersten Blick funktioniert es jetzt auch so dass keine doppelten Einträge mehr vorkommen. Aber nur bei einem Thread! Mit dem zweiten Thread müsste es aber genauso funktionieren, oder?
Also beispiel:
Thread 1 kommt an und will vertauschen. Er "nimmt sich" das Lock des Objekts.
Jetzt muss die Main-Methode die gerne ausgabe() aufrufen würde warten und der zweite Thread der auch vertauschen will muss auch warten. Wenn der erste Thread fertig ist gibt er das Lock ab und der nächste darf seine Methode aufrufen. So klingt das sehr logisch und es dürften so theoretisch keine doppelten Zahlen mehr vorkommen.
Scheint ebenfallls auch wieder zu funktionieren.
Stimmt das so vom Prinzip her wie ich das erklärt habe?
Und nochwas: Das Lock bezieht sich ja immer auf das Objekt...also sobald eine sychronized Methode aufgerufen wird, dürfen keine anderen synchronized methoden des Objekt aufgerufen werden, oder? Wenn ich noch eine Methode in dem Objekt hätte, die aber nicht synchronized ist, dann würde die aufgerufen werden können, auch wenn das Lock von einem anderem Thread gehalten wird, oder?
Lg.
L-ectron-X hat diesen Beitrag am 04.02.2008 um 18:16 Uhr editiert.
Code-Tags repariert.