java.lang.IllegalMonitorStateException: 线程在wait()前未锁定对象

6

但是我在它每次新建时都对 'roster' 对象进行同步。为什么?

有问题的代码:

 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;
}

你在哪里调用notify? - Ron
1个回答

8

"gets new'ed"的意思是你创建了一个新的花名册对象吗?

你确定你在正确同步吗?同步发生在实例而不是变量上。所以如果你这样做:

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

那么你只同步了的,而不是新的花名册

因此,以下代码应该会产生相同的错误:

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!
}

同步并不发生在 变量名 上,而是在 变量内容 上。如果您覆盖了该变量的内容,您不会重新与新值进行同步!


虽然您的观察是正确的,但我不明白它如何导致异常。您能详细说明一下吗? - kellogs
1
选项#1是如果roster.reload()可以以某种方式更改roster变量所引用的对象。 选项#2是,在到达wait()调用之前或在其中,某个其他线程更改了roster变量所引用的内容。 在任一情况下,您同步的Roster将不是您正在等待的相同Roster。 - Sbodd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接