[Java] Synchronized Methoden

q3tempest

Lieutenant
Registriert
Sep. 2002
Beiträge
595
Hi,
ich habe problem mit synchronisierten Methoden.
Ich hab 2 Thread erstellt, die auf einem gemeinsamen Variable zugreifen.
Ein Thread erhoert counter:long um 1, andere erniedrigt um 1.
Mit synchronisierten Block ( demoSyncObj() ) funktioniert, aber mit
synchronisierten Methoden ( demoSyncMed() ) ist counter nicht immer 0.
Wieso funktioniert synchronisierten Methoden nicht? Wo hab ich da Fehler uebersehen?

Temp

Code:
package testThread;

public class TestThread extends Thread {
	public static final long MAX = 100000;
	private long increment = 0;
	static long counter = 0;
	static Object o = new Object();
	
	
	public TestThread(long increment) {
		this.increment = increment;
	}
	
	
	public static void main(String[] args) {
		for (int i = 0; i < 4; i++) {
			TestThread thread1 = new TestThread(+1);
			TestThread thread2 = new TestThread(-1);
			long start = System.currentTimeMillis();
			thread1.start();
			thread2.start();
			try
			{
				thread1.join();
				thread2.join();
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
			long time = System.currentTimeMillis() - start;
			System.out.printf("Counter: %11d nach %6d ms\n",counter, time);
		}
	}
	
	
	public void demoUnsync() {
		for (long i= 0; i < MAX; i++) {
			counter = counter + increment;
		}
	}
	public void demoSyncObj() {
		for (long i= 0; i < MAX; i++) {
			synchronized(o) {
				counter = counter + increment;
			}
		}
	}
	public synchronized void demoSyncMed() {
		for (long i= 0; i < MAX; i++) {
			counter = counter + increment;
		}
	}
	
	
	public void run() {
		//demoUnsync();
		//demoSyncObj();
		demoSyncMed();
	}
}
 
Hier paar Console-Ausgabe:


demoSyncMed(): Synchronisierte Methoden

Counter: -83863 nach 79 ms
Counter: -391351 nach 62 ms
Counter: -48077 nach 15 ms
Counter: -44791 nach 32 ms


demoSyncObj(); Synchronisierte Block

Counter: 0 nach 4625 ms
Counter: 0 nach 5719 ms
Counter: 0 nach 4266 ms
Counter: 0 nach 4812 ms
 
Bei der synchronisierten Methode blockierst du das ganze Objekt, dass heißt den "TestThread". Jetzt hast du zwei Instanzen dieser Klasse und jede "lockt" sich selbst, wenn die Methode ausgeführt wird, somit wird die geteilte (statische) Ressource "counter" nicht richtig "gelockt" und es kommt zu dem bekannten Problem. Wenn du aber das (statische) Object "o" lockst, was du mittels "synchronized(o)" ja machst, bekommt ein Thread nur Zugriff auf "counter" wenn "o" frei ist.
Ich hoffe das ist halbwegs verständlich.
 
Ich hab heute morgen auch gemerkt. Hab dann einfach auf static geaendert.

Code:
public [B]static[/B] synchronized void demoSyncMed(long inc) {
     for (long i= 0; i < MAX; i++) {
          counter = counter + inc;
     }
}

Es funktioniert und endlich viel schneller als synchronized(Object).
Hier die Ausgabe:
Counter: 0 nach 16 ms
Counter: 0 nach 31 ms
Counter: 0 nach 16 ms
Counter: 0 nach 31 ms

Danke amarte!

Temp

P.S.: Kannst mir vielleicht noch erklaeren, warum synchronized(Object) viel langsamer als
synchronisierte Methoden?
 
Das synchronized(Object) ist bei dir wohl deutlich langsamer weil du es in der inneren Schleife MAX-mal aufrufst.

Mach das synchronized mal außerhalb der Schleife, dann sollte es ähnlich schnell sein.
 
Zurück
Oben