synchronized run() synchronisiert nicht

Steve222

Mitglied
Hallo allerseits,

kann mir jemand verständlich erklären, warum der folgende Code
NICHT verhindert, dass z.B. "X Y Y X" ausgegeben wird?
Ich dachte run() mit seinem write() Aufruf wird NICHT von einem
anderen thread gestört.


Java:
public class Buchstabe extends Thread {
private String name;

public synchronized void run() { write(); }     

public Buchstabe(String name) { this.name = name; }

public void write() {
    System.out.print(name);
    System.out.print(name);
}
    public static void main(String[] args) {
        new Buchstabe(" X ").start();
        new Buchstabe(" Y ").start();
    }
}


Ich Voraus schon vielen Dank für Eure Hilfe.

Viele Grüße

Steve222
 
Hallo,

weil es sich hier um zwei unterschiedliche Objekte handelt.
Es kann nur innerhalb eines Objektes synchronisiert werden. Das wäre ja schlimm, wenn es klassenweit wäre. ;-)

Wenn du das testen möchtest, musst du zwei Threads anlegen, die gleichzeitig versuchen die Methode auf einem Object aufzurufen.


Gruß

Sascha
 
Statt

Java:
public synchronized void run() { write(); }

kannst du über ein global verfügbares Objekt (z.B. eine Klasse) synchronisieren:

Java:
public void run() {
	synchronized (Buchstabe.class) {
		write();
	}
}
 
Hallo,

weil es sich hier um zwei unterschiedliche Objekte handelt.
Es kann nur innerhalb eines Objektes synchronisiert werden. Das wäre ja schlimm, wenn es klassenweit wäre. ;-)

Wenn du das testen möchtest, musst du zwei Threads anlegen, die gleichzeitig versuchen die Methode auf einem Object aufzurufen.


Gruß

Sascha

Hallo Sascha
und Danke. Ich verstehe es jedoch nicht wirklich.
Dass es sich um zwei Thread Objekte handelt ist/war mir soweit klar.
Warum schützt das Schlüsselwort "synchronized" vor run() nicht
davor, dass die Ausführung von run(), und alles was innerhalb run() passiert [z.B. der Aufruf und Ausführung von write() ], unterbrochen wird.
Warum wird write() gestört, obwohl es sich innerhalb "synchronized run()" befindet?

Was bedeutet
Es kann nur innerhalb eines Objektes synchronisiert werden.

und
...die Methode auf einem Object aufzurufen.....

Nicht gerade Klarheit bringt, dass ein Thread auch ein Objekt ist bzw. sein kann und umgekehrt.

Steve222
 
Ich denke, dass er meint, dass die Methode nur Instanceweit syncronisiert ist, also musst du write static machen und ihm dem Namen übergeben, damit es hinhaut.
 
Die Zeile

Java:
public synchronized void run() { 
  write(); 
}

ist das gleiche wie

Java:
public void run() { 
  synchronized(this) {
    write(); 
  }
}

Dadurch synchronisierst du über die jeweilige Instanz des Threads "Buchstabe". Da du nun 2 Threads/Instanzen erzeugst, ist der Lock/Monitor in beiden Threads verschieden. Was dir eben fehlt, ist ein Lock/Monitor, der in beiden Instanzen gleich ist.
 
Ich sehe ja jetzt erst, dass bei dir Buchstabe von Thread abgeleitet ist.

Mal ein Beispiel wie das funktioniert, was du gebaut hast (nur Buchstabe nicht als Thread).
Code:
public class SynchonizedExample {

	
	
	public synchronized void write(){
		System.out.println("A");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("B");
	}
	
	public static void main(String[] args) {
		final SynchonizedExample example = new SynchonizedExample();
		
		new Thread(){
			public void run() {
				
				example.write();
			};
		}.start();
		
		example.write();
	}
	
}

Also wenn das synchronized im Methoden-Header steht, wartet die Methode nur, wenn sie nochmal auf dem gleichen Object aufgerufen wird.

Gruß

Sascha
 
...
Dadurch synchronisierst du über die jeweilige Instanz des Threads "Buchstabe". Da du nun 2 Threads/Instanzen erzeugst, ist der Lock/Monitor in beiden Threads verschieden. Was dir eben fehlt, ist ein Lock/Monitor, der in beiden Instanzen gleich ist.

Es ist/war mir bekannt, dass der synchronized-Bereich durch synchronized(this) innerhalb der run() Definion notiert werden
kann und dass das gleiche ist.
Ich hatte gedacht, dass "synchronized(this) { <irgendein Code C1> }" dafür sorgt, dass <irgendein Code C1> ungestört
ausgeführt wird.
Dann ist es wohl der Scheduler, der write unterbricht und dafür verantwortlich ist, dass Ausgaben wie "X Y Y X" möglich sind!?

Du meinst höchstwahrscheinlich, dass die beiden Threads/Instanzen von des Threads "Buchstabe" eine gemeinsame
Synchronisationsvariable, sozusagen den SELBEN Lock/Monitor brauchen, über die/den sie miteinander kommunizieren.
können!?

Viele Grüße
Steve222
 
Du meinst höchstwahrscheinlich, dass die beiden Threads/Instanzen von des Threads "Buchstabe" eine gemeinsame
Synchronisationsvariable, sozusagen den SELBEN Lock/Monitor brauchen, über die/den sie miteinander kommunizieren.
können!?

Genau, denn mit synchronized(this) hast du 2 verschiedene Locks, die nichts miteinander zu tun haben!
 
Zurück