synchronised



  • Ich übe grad ein wenig Threading.

    Folgende Aufgabe:

    Es gibt eine Klasse Durchlauf. Ein Durchlauf hat eine Güte.
    Die Güte liegt zwischen 0 und 100%. EIn Durchlaufist ein schwieriges Unterfangen und sollte parallel durchgeführt werden.

    Es gibt eine Simulation. Hier sollen 5 Threads Durchläufe starten. Hat ein Durchlauf eine bessere Güte als der bisher beste soll der beste Durchlauf durch diesen ersetzt werden und der zugehörige Thread schlafen, so lange er noch der beste war. Nach 100 Durchläufen soll das Programm beendet werden.

    Ich habs mal probiert, bin aber bezüglicgh meines synchronised-Blockes nicht sicher.
    Snchronisiere ich zu viel oder zu wenig? Macht das Programm genau das, was ich will?

    Ich bekomme außerdem öfters IllegalMonitorState-Exceptions in wait() und notify()die ich nicht zuordnen kann.

    public class sim implements Runnable
    {
    	static int anzahl = 1;
    	static Durchlauf bester = new Durchlauf();
    
    	public void run()
    	{
    		System.out.println("TUE ETWAS");
    		Durchlauf d = new Durchlauf();
    		synchronized (sim.class)
    		{
    			while (anzahl != 100)
    			{
    				System.out.println(anzahl);
    				if (d.güte > bester.güte)
    				{
    					bester = d;
    					notify();
    					try
    					{
    						wait();
    					} catch (InterruptedException e)
    					{
    						e.printStackTrace();
    					}
    				}
    				anzahl++;
    			}
    		}
    	}
    
    	public static void main(String[] args) throws InterruptedException
    	{		
    		Thread[] threads = new Thread[5]; 
    		for(int i=0; i< 5; i++)
    		{
    			threads[i] = new Thread(new sim());
    		}
    
    		for(int i=0; i< 5; i++)
    		{
    			threads[i].start();
    		}
    
    		for(int i=0; i< 5; i++)
    		{
    			threads[i].join();
    		}
    
    		System.out.println(anzahl);
    		System.out.println(bester.güte);
    	}
    }
    

    Den Durchlauf hab ich einfach mit Random realisiert. Ist ja ohnehin nur ein Dummy



  • Bevor wir uns um inhaltliche Fragen kümmern, müssen wir die Exception loswerden: Du benutzt den Java-Monitor auf this , aber nur sim.class ist synchronized . Sobald also eine bessere Güte festgestellt wird, löst dein Call notify() ( this.notify() ) eine IllegalMonitorStateException aus.

    Wenn du auf den Typen synchronisieren willst, musst du notify und wait darauf aufrufen.



  • Bin noch einiges Durchgegangen:

    1. sim.class.notify() uind wait sollte die Exceptions loskrigen.

    2. Ich prüfe erst NACHDEM ich den Durchlauf durchgeführt habe, ob ich noch welche brauche.

    3. Ich mach nicht genug Durchläufe. Ich führe die Durchläufe außerhalb der while-Schleife aus. Erhöhe aber lustigerweise den Counter 🙂

    Hatte mich schon gewundert, warum manchmal ne Güte von 30 rauskam, bei 100 Durchläufen angeblich.

    Habe die Synch-Umgebung gespalten:

    einaml schau ich nach ob ich ncoh Durchläufe brauche.
    Dann ,nicht synchrnonisiert, new DUrchlauf(), danach den Rest meines sync-Blockes.

    Ich hoffe das behebt jetzt alle Schwierigkeiten



  • Noch eine kleine Frage:

    Mir fällt kein einziges sinnvolles Beispiel ein, in dem ich

    synchronised(this)

    brauche. Ich bin mir recht sicher, dass ich das schon recht oft gelesen habe.

    Aber wieso sollte ein Thread sich selbst als Lock-Object haben wollen?
    Auf seine Daten kann er doch problemlos zugreifen und diese auch gerne verändern, da kommen die anderen Threads ja nicht ran.
    Bei statischen Attributen müsste ich die Klasse nehmen und wenn Referenzen auf irgendwelche externen Objekte manipuliert werden, müste ich ja dise in synchronised schreiben? WOzu also synchronise(this)?



  • !"this" ist nicht der Thread, sondern ein Objekt der Klasse, in deren Methoden Du Dich gerade bewegst!

    Mit synchronized(this) wird also ein Objekt, z.B. eine Collection, gesperrt, damit nicht mehrere Threads sie gleichzeitig verändern.


Anmelden zum Antworten