2012-05-16 2 views
6

그러나 new'ed가되는 모든 곳의 'roster'객체에서 동기화됩니다. 어째서?java.lang.IllegalMonitorStateException : wait() 전에 스레드에 의해 객체가 잠기지 않았습니다.

기분을 상하게하는 코드 : "new'ed됩니다"와

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

reload()는 무엇을합니까? – Affe

+0

어디서이 관찰에 바로 당신이 – Ronnie

답변

8

당신이 새로운 명단 객체를 생성 의미?

제대로 동기화 하시겠습니까? 동기화가 인 경우 변수이 아니라 동기화가 발생합니다. 예를 들어

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

그런 다음 당신은 단지 이전 아닌 새로운 roster에 동기화.

그래서 다음 코드는 같은 오류가 발생한다 :

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 변수의 이름을 발생하지 않습니다,하지만 내용합니다. 내용을 덮어 쓰면 새로운 값으로 다시 동기화되지 않습니다!

+0

당신에게 전화를합니까, 나는 그것이 예외의 원인이 될 수있는 방법을 볼 수 없습니다. 당신은 정교 할 수 있습니까? – kellogs

+1

옵션 # 1은 roster.reload()가 어떻게 든 로스터 변수가 참조하는 객체를 변경할 수있는 것입니다. 옵션 # 2는 wait() 호출을하거나 호출하는 동안 다른 스레드가 명단 변수를 참조하는 것을 변경한다는 것입니다. 두 경우 모두, 당신이 동기화 한 명단은 당신이 기다리는 명단과 같은 명단이 아닙니다. – Sbodd

+0

수정 된 답장보기 –

관련 문제