getClass()-Methode



  • Mir ist nicht 100%ig klar was die getClass()-Methode von Object macht. In der Java API-Doku steht:

    Returns the runtime class of an object. That Class object is the object that is locked by static synchronized methods of the represented class.

    Von welchem Objekt wird die runtime class zurückgegeben? Kann mir jemand anschaulich erklären was mit dem Satz "That Class object is the object that is locked by static synchronized methods of the represented class." gemeint ist?



  • Es wird das tatsaechliche Class Objekt zurueck gegeben.

    Du kannst ja getClass() auf jedes objekt anwenden von dem du den genauen Type nicht weisst. getClass liefert dir den echten Typen (also maximal downgecastet).

    class Base {
    }
    
    class Derived extends Base {
    }
    
    Base x = new Derived();
    x.getClass(); // == Derived.class
    

    Der Satz den du nicht verstehst heisst, dass wenn du synchronized static methoden in der Klasse hast, der Compiler folgendes sieht:

    class C {
      static synchonized void foo() {
        bar();
      }
    }
    

    das wird zu

    class C {
      static void foo() {
        synchronized(C.class) {
          bar();
        }
      }
    }
    


  • Aha, ich habe folgenden Code geschrieben:

    public void insertThread( ThreadMetaInfo newThread ) {
    		synchronized(getClass()) {
    			int index = isInList( newThread.threadId );
    			if( index != -1 ) {
    				list.remove(index);
    				list.addFirst( newThread ); 
    			} else {
    				if( list.size() >= maxElements )
    					list.removeLast();
    				list.addFirst( newThread );
    			}
    		}
    	}
    

    Thread bedeutet hier in der Methode allerdings was anderes als ein Java-Thread. Meine Fragen die ich dann jetzt habe:
    1. Wenn ich nun getClass() aufrufe, dann wird "this" zurückgegeben?
    2. Habe ich nun zwei Java-Threads zB A und B, wird dann B ausgeschlossen falls erst A die Methode aufruft und dann B? Nach meiner Vermutung 1 müsste das der Fall sein, wenn getClass() den this Zeiger zurückgibt (Thread A und B erhalten die selbe Instanz des Objekts.)?



  • getClass() liefert ein Class-Object zurueck. http://java.sun.com/javase/6/docs/api/java/lang/Class.html

    Dass hier ist unnoetig:

    public void insertThread( ThreadMetaInfo newThread ) {
            synchronized(getClass()) {
    

    Ein einfaches

    public synchronized void insertThread( ThreadMetaInfo newThread ) {
    

    reicht.

    http://jerry.c-lab.de/java/21Tage/kap18.htm

    Das Schlüsselwort synchronized fordert Java auf, den Codeblock in der Methode Thread-tauglich zu machen. Dadurch ist es nur jeweils einem Thread gestattet, in diese Methode einzudringen. Die anderen müssen warten, bis der laufende Thread beendet ist, erst dann können sie beginnen. Das bedeutet, daß es nicht ratsam ist, eine große längere Methode zu synchronisieren. Alle Threads würden irgendwann an diesem Engpaß steckenbleiben und warten, bis sie bei dieser einen schwerfälligen Methode an die Reihe kommen.



  • Okay, wenn ich das mit dem Klassenobjekt und den Kopien davon (den Instanzen) richtig verstanden habe, dann sollte mein Beispiel

    public void insertThread( ThreadMetaInfo newThread ) {
            synchronized(getClass()) {...
    

    aber genauso funktionieren wie

    public synchronized void insertThread( ThreadMetaInfo newThread ) {...
    

    Wobei letzteres natürlich schöner ist.



  • tomatesalat schrieb:

    Okay, wenn ich das mit dem Klassenobjekt und den Kopien davon (den Instanzen) richtig verstanden habe, dann sollte mein Beispiel

    public void insertThread( ThreadMetaInfo newThread ) {
            synchronized(getClass()) {...
    

    aber genauso funktionieren wie

    public synchronized void insertThread( ThreadMetaInfo newThread ) {...
    

    Wobei letzteres natürlich schöner ist.

    Das sind zwei verschiedene Sachen! Die synchronisierte (nicht-statische) Methode entspricht einem synchronized(this)-Block. Auf getClass() zu synchronisieren hat eine völlig andere Bedeutung. Hier wird auf das Class-Objekt synchronisiert und davon gibt es nur eins für deine Klasse. Objekte kann es aber viele geben.

    Wenn du in Java Nebenläufigkeit unterstützen willst, solltest du dir auf jeden Fall das Concurrency-Framework ansehen (ab Java 1.5 in der Standard-API). Damit wird vieles einfacher und sicherer als mit dem lowlevel synchronized.



  • tfa schrieb:

    Das sind zwei verschiedene Sachen! Die synchronisierte (nicht-statische) Methode entspricht einem synchronized(this)-Block. Auf getClass() zu synchronisieren hat eine völlig andere Bedeutung. Hier wird auf das Class-Objekt synchronisiert und davon gibt es nur eins für deine Klasse. Objekte kann es aber viele geben.

    Ja und? Dann ist halt das Klassenobjekt das Synchronisationsobjekt. Wo ist denn jetzt der Unterschied zu synchronized(this), außer dass nun auch unterschiedliche Instanzen ausgeschlossen werden? Die Auswirkungen sollten die gleichen sein, wenn es nur eine Instanz meines Objektes gibt.



  • Wenn es nur ein Exemplar gibt, kommt es auf das selbe raus (aber du schriebst was von "den Instanzen"). Trotzdem sollte man gegen "this" synchronisieren, man weiß nie, was in der Zukunft noch dazu kommen kann.



  • Super, vielen Dank für Eure Antworten.



  • Die Synchronisation ist nicht gewährleistet, wenn du auf this lockst, falls du mehrer Objekte hast und die Threads auf verschiedene Objekte zugreifen.
    In dem Fall auf das Klassenobjekt oder ein dezidiertes Lockobjekt locken.



  • cof schrieb:

    Die Synchronisation ist nicht gewährleistet, wenn du auf this lockst, falls du mehrer Objekte hast und die Threads auf verschiedene Objekte zugreifen.

    Jedes Objekt hat seinen eigenen Zustand. Selbstverständlich können verschiedene Threads gleichzeitig auf verschiedene Objekte zugreifen, ohne dass es Synchronisazionsprobleme mit synchronized(this) gibt.

    cof schrieb:

    In dem Fall auf das Klassenobjekt oder ein dezidiertes Lockobjekt locken.

    Klar geht das, aber es hat eine andere Bedeutung.



  • ich schriebe nicht, dass es probleme gibt. nur, dass du aufpassen musst auf welches Objekt du synchronisierst. wenn du auf this syncs und du hast mehr als ein Objekt, dann nützt dir nein Lock genau null, weil es eben nicht das selbe Objekt ist. in dem fall sicher stellen, dass es das selbe objekt ist, also entweder class objekt oder ein lock-objekt.



  • cof schrieb:

    ich schriebe nicht, dass es probleme gibt. nur, dass du aufpassen musst auf welches Objekt du synchronisierst. wenn du auf this syncs und du hast mehr als ein Objekt, dann nützt dir nein Lock genau null, weil es eben nicht das selbe Objekt ist. in dem fall sicher stellen, dass es das selbe objekt ist, also entweder class objekt oder ein lock-objekt.

    Nein, nochmal: verschiedene Objekte, verschiedene Zustände. Threads werden pro Objekt synchronisiert. Siehe z.B. Vector oder Hashtable. Die sind auch nur gegen "this" synchroniert, obwohl es viele Objekte davon geben kann.

    Alles andere (globales Monitor-Objekt oder Klassenobjekt) ist ein völlig anderer Anwendungsfall und eher selten.



  • MeinObjekt ob1 = new MeinObjekt();
    

    wenn irgendwo im MeinObjekt Code

    synchonized(this) {..}
    

    steht und 2 verscheidene Threads eine Instanz von MeinObjekt haben, dann ist der Block NICHT synchronisiert, weil 2 verschiedene Instanzen.
    sollte allerdings

    synchronized(MeinObjekt.class) {..}
    

    stehen, dann ist der entsprechende Codeblock synchronisiert, da MeinObjekt.class für beide Threads das gleiche Objekt ist.



  • cof schrieb:

    MeinObjekt ob1 = new MeinObjekt();
    

    wenn irgendwo im MeinObjekt Code

    synchonized(this) {..}
    

    steht und 2 verscheidene Threads eine Instanz von MeinObjekt haben, dann ist der Block NICHT synchronisiert, weil 2 verschiedene Instanzen.
    sollte allerdings

    synchronized(MeinObjekt.class) {..}
    

    stehen, dann ist der entsprechende Codeblock synchronisiert, da MeinObjekt.class für beide Threads das gleiche Objekt ist.

    Da die beiden Objekte aber keinen shared state haben, ist eine synchroniesierung zwischen den beiden objekten _nicht_ notwendig.


Anmelden zum Antworten