2012-05-16 10 views
6

Ale synchronizuję obiekt "roster" wszędzie, gdzie jest on nowy. Dlaczego ?Wyjaśnienie java.lang.IllegalMonitorStateException: obiekt nie jest zablokowany przez wątek przed odczekiem()

Kod wykraczająca:

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

co robi przeładowanie()? – Affe

+0

gdzie zadzwonić powiadomić – Ronnie

Odpowiedz

8

Z "dostaje new'ed" znaczy utworzyć nowy obiekt zaplanowany?

Czy jesteś pewien, że synchronizujesz poprawnie? Synchronizowanie odbywa się na instancjach, a nie na zmiennych. Więc jeśli zrobisz np.

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

Wtedy tylko zsynchronizowana z starego, a nie nowyroster.

więc następujący kod powinien produkować ten sam błąd:

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 nie zdarza imienia zmiennej, ale na treści. Jeśli zastąpisz zawartość, nie dokonasz ponownej synchronizacji z nową wartością!

+0

, jeśli masz rację w tej obserwacji, nie widzę, jak może to być przyczyną wyjątku. Czy możesz rozwinąć ? – kellogs

+1

Opcja nr 1 byłaby, gdyby plik roster.reload() mógł jakoś zmienić obiekt, do którego odnosi się zmienna rosterowa. Opcja # 2 polega na tym, że zanim dojdziesz do wywołania wait() lub gdy jesteś w nim, inne wątki zmieniają to, do czego odnosi się zmienna rosterowa. W obu przypadkach zestaw, na którym się zsynchronizujesz, nie będzie tym samym zestawem, na który czekałeś(). – Sbodd

+0

Zobacz edytowaną odpowiedź. –

Powiązane problemy