2012-05-16 6 views
6

Aber ich bin auf dem "Roster" -Objekt synchronisieren überall wo es neu wird. Woher ?java.lang.IllegalMonitorStateException: Objekt nicht vor dem Warten durch den Thread gesperrt()

Der problematische Code:

public Roster getRoster() { 
    if (roster == null) { 
     return null; 
    } 

    if (!roster.rosterInitialized) { 
     try { 
      synchronized (roster) { 
       roster.reload(); 
       long waitTime = SmackConfiguration.getPacketReplyTimeout(); 
       long start = System.currentTimeMillis(); 
       while (!roster.rosterInitialized) { 
        if (waitTime <= 0) { 
         break; 
        } 
        roster.wait(waitTime); 
        long now = System.currentTimeMillis(); 
        waitTime -= now - start; 
        start = now; 
       } 
      } 
     } 
     catch (InterruptedException ie) { 
      // Ignore. 
     } 
    } 
    return roster; 
} 
+2

was macht reload()? – Affe

+0

wo nennst du notify – Ronnie

Antwort

8

Mit "wird new'ed" Sie meinen, Sie ein neues Roster-Objekt erstellen?

Sind Sie sicher, dass Sie richtig synchronisieren? Die Synchronisation erfolgt auf Instanzen, nicht auf Variablen. Wenn Sie z.B.

synchronized(roster) { 
    roster = new Roster(); 
    // do something 
} 

Dann nur Sie auf die alten synchronisiert, nicht die neueroster.

So ist der folgende Code sollte den gleichen Fehler erzeugen:

Roster roster = new Roster(); 
Roster othervariable = roster; 
synchronized(othervariable) { 
    roster = new Roster(); // create a new roster 
    othervariable.wait(1000); // OK, since synchronized with this instance! 
    roster.wait(1000); // NOT OK, not synchronized with *new* roster! 
} 

Synchronizsation geschieht nicht auf dem Name der Variablen, sondern auf den Inhalt . Wenn Sie den Inhalt überschreiben, synchronisieren Sie den neuen Wert nicht erneut!

+0

wo du in dieser Beobachtung richtig bist, kann ich nicht sehen, wie es die Ursache der Ausnahme sein könnte. Kannst du es ausarbeiten? – kellogs

+1

Option # 1 wäre, wenn roster.reload() irgendwie das Objekt ändern könnte, auf das sich die Roster-Variable bezieht. Option 2 ist, bevor ein Aufruf von wait() oder während Sie drin sind, ein anderer Thread ändert, worauf sich die Roster-Variable bezieht. In beiden Fällen ist der Roster, den Sie synchronisiert haben, nicht derselbe Roster, auf den Sie warten. – Sbodd

+0

Siehe die bearbeitete Antwort. –

Verwandte Themen